使用私有静态方法的优点

Ner*_*ury 197 c# performance

在创建具有内部私有方法的类时,通常为了减少代码重复,不需要使用任何实例字段,将方法声明为静态是否具有性能或内存优势?

例:

foreach (XmlElement element in xmlDoc.DocumentElement.SelectNodes("sample"))
{
    string first = GetInnerXml(element, ".//first");
    string second = GetInnerXml(element, ".//second");
    string third = GetInnerXml(element, ".//third");
}
Run Code Online (Sandbox Code Playgroud)

...

private static string GetInnerXml(XmlElement element, string nodeName)
{
    return GetInnerXml(element, nodeName, null);
}

private static string GetInnerXml(XmlElement element, string nodeName, string defaultValue)
{
    XmlNode node = element.SelectSingleNode(nodeName);
    return node == null ? defaultValue : node.InnerXml;
}
Run Code Online (Sandbox Code Playgroud)

将GetInnerXml()方法声明为静态是否有任何优势?没有意见回复,我有意见.

Sco*_*man 211

FxCop规则页面上:

将方法标记为静态后,编译器将向这些成员发出非虚拟调用站点.发出非虚拟调用站点将阻止在运行时检查每个调用,以确保当前对象指针为非null.这可以为性能敏感的代码带来可测量的性能提升.在某些情况下,无法访问当前对象实例表示正确性问题.

  • 我还要补充说,"静态"子句不会造成伤害,并且已经提供了一些含有1个单词的"文档".它告诉您此方法未使用任何实例成员,并且您几乎可以免费获得此文档 (32认同)
  • 我会说:"如果一个方法不需要状态访问(这个),那就把它作为一般规则". (18认同)
  • 许多开发人员不熟悉“私有静态”。我在团队的通用代码库中使用了它,并导致混乱。作为回报,它提供的好处很小。我们可以选择教育团队中的每个人,包括将来维护代码的所有开发人员,这意味着什么。但是将私有方法切换到私有静态的好处很小(即消除对实例数据的依赖),这不值得付出努力和困惑。无论哪种方式,该方法都已经是专用的。这是一种实际上不需要知道的语言怪癖。 (4认同)
  • 为了平衡,值得指出的是,很多人一般都反对静态方法,因为它们打破了多态性,并且意味着对象不能用于测试.例如,请参阅http://googletesting.blogspot.co.uk/2008/12/static-methods-are-death-to-testability.html (3认同)
  • @Andy——好点。划清界限的一种方法是查看静态方法是否正在访问您传入的参数之外的任何内容。只要它以这种方式独立,就应该很容易测试,并且没有必要存根任何东西。 (2认同)

Nei*_*eil 89

当我写一堂课时,大多数方法分为两类:

  • 使用/更改当前实例状态的方法.
  • Helper方法不使用/更改当前对象的状态,但帮助我计算其他地方需要的值.

静态方法很有用,因为只要查看它的签名,就会知道调用它不会使用或修改当前实例的状态.

举个例子:

public class Library
{
    private static Book findBook(List<Book> books, string title)
    {
        // code goes here
    }
}

如果一个库状态的实例变得搞砸了,而我正在试图弄清楚为什么,我可以排除findBook作为罪魁祸首,只是从它的签名.

我尝试使用方法或函数的签名尽可能多地进行通信,这是一种很好的方法.

  • 真的。在这种情况下,签名会告诉我们这个方法可以访问(并有能力改变)Library 的一个实例。 (2认同)

Mar*_*kac 80

对静态方法的调用会生成Microsoft中间语言(MSIL)中的调用指令,而对实例方法的调用会生成callvirt指令,该指令还会检查空对象引用.但是,大多数时候两者之间的性能差异并不显着.

src:MSDN - http://msdn.microsoft.com/en-us/library/79b3xss3(v=vs.110).aspx


Ken*_*art 15

是的,编译器不需要将隐式this指针传递给static方法.即使您不在实例方法中使用它,它仍然被传递.

  • 传递一个额外的参数意味着CPU必须做额外的工作才能将该参数放在寄存器中,如果实例方法调用另一个方法,则将其推送到堆栈中. (11认同)

Joe*_*orn 5

这迫使您记住还将函数使用的任何类范围成员声明为静态,这应该节省为每个实例创建这些项目的内存。

  • 不,但如果它由静态方法使用,那么它_必须_是静态的。如果该方法不是静态的,那么您可能没有将类成员设为静态,这将导致该类的每个实例使用更多内存。 (3认同)

Fre*_*est 5

由于没有传递这个参数,它会稍快一些(虽然调用方法的性能成本可能远远超过这个节省).

我会说我能想到私有静态方法的最好理由是它意味着你不能意外地改变对象(因为没有这个指针).