静态方法更有效吗?

Yar*_*veh 46 c# performance static-methods

在内存和时间方面,使方法静态更好吗?

Han*_*ant 86

通常是的,没有必要传递"this"引用.该引用在ECX寄存器中传递,因此不需要额外的堆栈空间.如果您从同一类的实例方法进行调用,则已设置该寄存器,根本不会有任何节省.但是当方法在另一个类中时,它可以帮助缓解x86 CPU核心的压力,x86没有很多寄存器.看到可测量的性能改善将非常罕见.

我虔诚地将不使用实例成员的类的方法标记为静态.我重视static关键字提供的固有契约:"此方法不会改变对象状态."

  • 最后一段的+1 - 这真的很重要,它使`静态`非常宝贵. (18认同)
  • 逻辑胜过任何一天的意见。 (2认同)

LBu*_*kin 54

如果方法不需要来自类所属的任何状态信息,则应该使方法成为静态方法.

如果你不关心多态,你可以通过决定是否接受类实例成员并将它们作为参数传递给方法来将任何方法写为实例或静态.您应该考虑的是,语法是否自然,代码是否易于理解和有意义,等等.

您可能不应该担心在此级别进行优化,因为实例与静态方法的性能开销可以忽略不计.是的,在调度表中使用了一些类型的空间(如果方法是虚拟的) - 但它是一个微小的,恒定的开销.是的,调用实例方法与静态方法的开销也很小 - 但同样很小.

这似乎是微观优化的一个层次,除非你有可衡量的,有形的证据表明相信实际上影响了程序的性能,否则你应该避免.事实上,如果你做的事情错了,传入其他参数的成本(将它们复制到堆栈等),而不是通过隐藏的访问它们this的类型的引用,可能会导致糟糕的性能.

您最好分析方法的语义,并在此基础上进行静态/实例决策.

  • 引用Great Jeff Atwood - 您可以用任何语言编写Fortran. (8认同)
  • 我的理解是,Microsoft C#生成的IL代码对所有实例方法使用虚拟调度(callvirt),无论它是否为虚拟,即使对于密封类也是如此.这是使用callvirt的内置空值检查.否则,必须对空检查进行编码,因为CLR在空实例上调用实例方法没有问题. (2认同)
  • @Mathias:是的,静态方法本身很容易测试,但你不能覆盖它们并用存根替换它们.例如,如果您的静态方法命中数据库并且您正在测试该类,则无法覆盖它并让它返回预先填充的集合.但这些只是细节,不同的测试策略会处理这种情况.我想我只是在'不喜欢静态方法'阵营. (2认同)

Mar*_*ell 9

如果你打算传递实例(SomeStaticMethod(obj, "abc", 123);),那么不是真的.您只能在没有多态性的场景中有用地使用静态方法,在这种情况下,很可能无论如何都会内联任何类似属性的简单事物.

使用对象"自然"( obj.SomeMethod("abc",123);)-保持代码的简洁,并且轮廓找出性能问题-这是非常不可能的实例和静态之间的区别,除非你正在运行一些非常紧密的循环.这里一些场景中它可能无所谓,但他们很专业.


Chr*_*ser 5

静态方法和非虚拟实例方法之间几乎没有区别.后者只是将thisprointer/reference作为"隐藏"参数.在生成的机器代码中,两种调用看起来非常相似.

如果方法不依赖于/修改对象,则该方法应该是静态的.

另一方面,虚方法(可覆盖)要求调用者在所谓的vtable中查找确切的实现.除了阻止编译器内联非常小的方法(经常内联简单属性访问器)之外,查找还需要几个周期.

但是,虚拟方法是CLR中C#/中可用的最快的动态调度方式.比代表和反思快得多.