2010-06-10 104 views
19

我在我的ASP.NET Web應用程序的公共類中聲明瞭幾個全局方法。Static Vs實例方法性能C#

我必須聲明的公共類的所有全局方法如下格式

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指令實現,這會導致輕微的開銷。請注意,將您的方法更改爲靜態方法對於雄心勃勃的性能目標不太可能有幫助,但 它可以提供一點幫助,並可能導致進一步降低。

我很困惑哪一個使用?

+0

您是否閱讀過第一個鏈接的結尾?即使在線程內部,關於自動鎖定的斷言也是錯誤的。 – 2010-06-10 17:24:43

回答

42

你的第一個鏈接狀態:

那是因爲靜態方法使用 鎖是線程安全的。總是做 內部一個Monitor.Enter()和 Monitor.exit(),以確保線程安全

也就是完全,可怕的,可恨錯誤。


如果您將[MethodImpl(MethodImplOptions.Synchronized)]添加到該方法,該語句將變爲部分爲真。

添加此屬性將導致CLR在lock(typeof(YourClass))中包裝static方法,並在lock(this)中包含實例方法。

This should be avoided where possible


你的第二個環節是正確的。
Static methods are a little bit faster than instance methods,因爲他們沒有一個this參數(因此跳過從callvirt指令NullReferenceException檢查)

+0

謝謝這很有幫助。 – dotnetguts 2010-06-10 17:42:10

+9

+1對於漂亮的形容詞:) – SWeko 2010-06-10 17:56:03

5

我傾向於照顧甚少在這方面的表現。真正有用的靜態方法是強制實施功能性實踐。例如,如果您在您的實例類中創建了一個私有靜態幫助器方法,那麼您就會明白該方法不能修改實例的狀態。

+0

非常好的一點。 – 2014-11-25 10:59:50

0

這基本上是一個設計選擇。如果您的邏輯包括創建類的實例和更新某些屬性,請參閱實例方法,因爲靜態方法將在實例之間共享。雖然如果你有一些實用的功能,如做一些字符串操作,創建一個連接字符串等。這不涉及對象操作,去靜態方法。

2

我個人總是會選擇更好的方法來完成當前的任務,並編寫穩定,易讀和易於維護的代碼。

還有其他方法可以提高應用程序的性能。

一些例子:

  • 如果你想用一個簡單的方法多次,不用每次都實例化一個對象(一個輔助功能),然後在靜態類使用靜態方法。

  • 如果您的方法訪問類中的其他變量並且不是線程安全的,請使用s成員函數。

  • 在asp.net中,如果您想要跨會話共享對象,或者您可以使用內部緩存結果的方法提高性能,靜態方法也可以。

  • 您可以混合兩種方式並使用工廠設計模式來創建具有某些成員函數的類,但是您確保一次只有一個實例。

  • 有時一個靜態功能,可避免愚蠢的錯誤或減少的額外運行時檢查的必要性:

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

但總體來說它完全依賴於當前的任務。沒有簡單的「總是使用這種方法......」回答你的問題。

+0

感謝SchlaWiener回答。 我聲明瞭多次使用的實用方法,並且從可維護的方法來看都很好,但是我對一個線程中提到的方法的鎖定感到困惑。 – dotnetguts 2010-06-10 17:41:13

+0

實際上,您現在可以使用可使用空值的擴展方法,因此thisstringisnull.IsNullOrEmpty()可能有意義。 – SWeko 2010-06-10 17:57:33

+0

@Sekeko:真的嗎?不知道那個。這對每個擴展方法都是如此,或者如果我編寫擴展方法,我需要添加一些額外的代碼? – 2010-06-10 20:07:56