C#中的静态方法?

3
静态方法相对于非静态方法的性能问题是什么?我读过静态方法在性能方面更好,但我想知道它们为什么更快?如果一个方法没有使用任何实例成员,则编译器应该将其视为静态方法并处理。
6个回答

7

编辑:Eric在这里进一步解释了这个问题,并暗示call有时会被使用...虽然需要注意的是,他的new()示例并不保证;-p


在原始编译器(1.1之前)中,编译器确实将没有this的非虚拟实例方法视为静态方法;问题在于这导致了一些与null检查相关的奇怪问题,即:

obj.SomeMethod();

没有 抛出异常(对于 obj=null 和非虚方法 SomeMethod 未访问 this 的情况)。如果你改变了 SomeMethod 的实现方式,这将是不好的。当他们调查添加显式空检查的成本时(即先进行空检查再进行静态调用),结果证明与使用虚拟调用是相同的,因此他们选择了后者,使其变得更加灵活和可预测。

请注意,如果 SomeMethod 是扩展方法(静态方法),那么"不抛出异常"也完全符合行为。

我认为在某个时候,您可以发出IL来通过静态调用调用一个常规实例方法,但是上次我尝试时,CLR给我返回了 "oh no you don't!" 消息(此操作可能会破坏运行时);要么他们完全阻止了这一点,要么(更有可能)是我搞坏了自定义的IL。


我已经阅读了C++编译器可以这样做,那为什么他们不让C#编译器变得更智能呢? - viky
这不是关于聪明的问题...就像我解释的那样,使用“null-check和静态调用”与使用内置了null-check的“虚拟调用”之间没有明显的区别。那么为什么要有两个不同的选项来维护呢? - Marc Gravell

5
是的,静态调用会更快 - 在调用方法之前不需要创建对象实例。(尽管你显然不会注意到这种差异)
在实际情况下,如果编译器优化了一个方法(使实例方法变为静态方法),实际上并没有什么影响 - 除非你已经创建了该实例,否则你不会调用实例方法,对吧?
归根结底,你应该尝试优化代码的可维护性,而不是试图在这里或那里节省3个纳秒。

我希望我们的C#编译器能够像C++编译器一样聪明,做到这种优化。感谢您的解释!! - viky

3
请参见此问题
以下是摘录:

每次调用实例方法时,静态调用比构造一个实例快4到5倍。但是,我们仍然只谈论每次调用数十纳秒。


2
请注意,这是与每次调用构造新实例进行比较;它不比较通常情况下仅为多个调用构造一次实例的情况。 - John Saunders
3
如果你只是在提及另一个问题的答案,为什么不直接将链接作为评论发布或标记为重复呢? - Marc Gravell
1
还要注意的是,该文章是在2003年发布的。自那时以来,CLR已经发生了很大变化。 - Jon Skeet

1

我怀疑编译器不会将其视为静态方法,但您可以自行检查。好处是不需要创建实例,无需担心垃圾收集器,如果有静态构造函数,则只需调用它。


C++编译器可以做到,为什么.NET(C#)编译器不能呢? - viky

0

静态方法很快,因为不需要构造实例。

如果你只需要创建一个实例并保存静态成员,那么性能是相等的。

它们在总体性能上非常小。

所以......


0

是的,静态方法很快,但静态变量所占用的内存不受GC控制,即使不需要也不会被释放,这是一个问题。

但最重要的是,您应该考虑应用程序的设计,因为内存和速度已经增加了几天,如果您不正确使用静态变量,则可能导致设计不佳。


你不需要拥有一个静态变量来调用一个静态方法。它们是不同的概念。 - George V. Reilly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接