静态方法和实例方法的性能比较 C#

20

我在我的ASP.NET Web应用程序中声明了一些全局方法,这些方法都在公共类中声明。

我有一个习惯,在以下格式的公共类中声明所有全局方法:

public static string MethodName(parameters) { }

我想知道这对性能有何影响?

  1. 哪个更好?静态方法还是非静态方法?
  2. 为什么更好?

http://bytes.com/topic/c-sharp/answers/231701-static-vs-non-static-function-performance#post947244指出:

因为静态方法使用锁来实现线程安全,内部始终执行Monitor.Enter()和Monitor.exit()以确保线程安全。

http://dotnetperls.com/static-method则指出:

相比实例方法,静态方法在调用栈上通常更快。在C#编程语言中,有几个原因可以解释这一点。实例方法实际上将‘this’实例指针作为第一个参数使用,因此实例方法总是具有该开销。此外,实例方法使用callvirt指令来实现,这会带来轻微的开销。请注意,将您的方法更改为静态方法不太可能对提高性能目标有所帮助,但它可能会稍微有所帮助,并可能导致进一步的减少。

我有点困惑该使用哪个?


你读完了第一个链接吗?即使在帖子中,很明显关于自动锁定的断言是错误的。 - Dan Tao
4个回答

46

你的第一个链接中提到:

这是因为静态方法使用锁来保证线程安全。它们在内部始终执行 Monitor.Enter() 和 Monitor.exit() 来确保线程安全。

这是完全、极其、令人发指地错误的。


如果将 [MethodImpl(MethodImplOptions.Synchronized)] 添加到方法中,那么该语句就部分正确了。

添加此属性会导致 CLR 将 static 方法包装在 lock(typeof(YourClass)) 中,将实例方法包装在 lock(this) 中。

在可能的情况下应避免使用此方法。


你的第二个链接是正确的。
静态方法比实例方法稍微快一点,因为它们没有一个"this"参数(从而跳过了callvirt指令中的NullReferenceException检查)

7

在这方面,我往往对性能关注得很少。静态方法真正有用的地方在于强制实施功能性实践。例如,如果您在实例类中创建了一个私有静态辅助方法,则可以放心地知道该方法无法修改实例的状态。


2

我个人会选择更好地完成当前任务的方法,并编写稳定、易读和易于维护的代码。

还有其他提高应用程序性能的方法。

以下是一些示例:

  • If you want to use a simple method multiple times without instancing an object every time (a helper function) then use a static method in a static class.

  • If your method accesses other variables in the class and is not thread safe use s member function.

  • In asp.net if you want to share an object accross sessions or you can improve performance with a method that internally caches the result a static method would be fine, too.

  • You can mix both ways and use the factory design pattern to have a class with some member functions, but you ensure that there is always only one instance at a time.

  • Sometimes a static function can avoid stupid errors or reduces the need of additional runtime checks:

    String.IsNullOrEmpty(thisstringisnull)  // returns true
    thisstringisnull.IsNullOrEmpty() // If Microsoft would have implemented
                                     // the method this way you would get a
                                     // NullReferenceException
    

总的来说,这完全取决于当前的任务。对于你的问题,没有简单的“总是使用这种方法...”的答案。


感谢SchlaWiener的回答。我声明了一些实用方法,这些方法被多次使用,并且从可维护的角度来看很好,但是我对方法锁定感到困惑,正如在一个线程中提到的那样。 - dotnetguts
现在你可以使用扩展方法来处理空值,所以这个字符串的判断是否为空的方法 thisstringisnull.IsNullOrEmpty() 是有意义的。 - SWeko
@SWeko:真的吗?我不知道这个。每个扩展方法都是这样吗,还是如果我编写一个扩展方法需要添加一些额外的代码? - Jürgen Steinblock
嗯,扩展方法只是语法糖,除了调用站点的外观之外,第一个参数没有什么特别的。所以是的,这适用于任何扩展方法。 - SWeko

0

这基本上是一个设计选择。如果您的逻辑包括创建类实例并更新一些属性,请使用实例方法,因为静态方法将在实例之间共享。而如果您有一些实用函数,比如进行一些字符串操作、创建连接字符串等,不涉及对象操作,请使用静态方法。


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