2009-12-14 69 views
3

靜態方法對非靜態方法的性能問題是什麼?我已經讀過靜態方法在性能方面更好,但我想知道它們是如何更快的?如果一個方法沒有使用任何實例成員,那麼我們的編譯器應該照顧它並將其視爲靜態方法。C#中的靜態方法?

回答

7

編輯:埃裏克評論更多關於這here,並暗示有當使用call一些時間......但請注意他的new()例如isn't guaranteed ;-p


在原來的編譯器(1.1之前),編譯器確實將非虛擬實例方法(沒有this)視爲靜態;的問題是,這會導致和null檢查一些奇問題,即

obj.SomeMethod(); 

沒有拋出異常(obj=null和非虛擬方法SomeMethod其中沒有觸及this)。如果您更改了SomeMethod的實施,那麼這很糟糕。當他們調查了添加顯式空值檢查(即空檢查和靜態調用)的成本後,結果與使用虛擬調用相同,因此他們這樣做,這使得它更加靈活,可預測。

請注意,「不拋出異常」也是完全行爲如果SomeMethod是擴展方法(靜態)。

我覺得在一個點上,你可能會釋​​放出IL通過靜態調用調用定期實例方法,但我最後一次嘗試,我得到了「哦,不,你不知道!」來自CLR的消息(此操作可能會破壞運行時的穩定性);要麼他們完全阻止了這一點,要麼(可能更有可能)我把自定義的IL放到了一邊。

+0

我讀過C++編譯器這樣做,爲什麼他們沒有讓C#編譯器變得那麼聰明? – viky 2009-12-14 07:09:23

+0

這不是關於聰明......就像我解釋的那樣,在執行「空檢查和靜態調用」與「虛擬調用」(內置空檢查)之間沒有任何明顯差異。那麼爲什麼有兩個不同的選項要維護? – 2009-12-14 07:16:20

3

請參閱this question

下面是摘錄:

一個靜態調用爲4〜5倍,構建每次 一次調用一個實例方法的實例更快 。 然而,我們仍然只是討論 約幾十納秒的每次通話

+2

請注意,這是比較爲每個呼叫構造一個新的實例;它不會比較一次構建實例的更常見情況,用於多次調用。 – 2009-12-14 06:18:29

+3

如果您只是*提及另一個問題的答案,爲什麼不直接發佈鏈接作爲評論,或投票重複? – 2009-12-14 06:24:16

+1

另外請注意,那篇文章早在2003年.CLR已經發生了很大變化。 – 2009-12-14 06:59:22

1

我懷疑,編譯器將把它作爲一個靜態方法,雖然可以檢查自己。好處不是創建實例。沒有垃圾收集器擔心。只有被調用的靜態構造函數,如果有的話。

+0

C++編譯器是否這樣做,爲什麼不.Net(C#)編譯器 – viky 2009-12-14 06:41:55

0

靜態方法快,因爲構造一個實例

買,如果你只創建一個實例,並保存靜態成員,性能等於

他們都非常小,整體性能

所以... ....

5

是的靜態調用會更快 - 在調用方法之前,您不需要創建對象的實例。 (雖然你顯然不會注意到它們之間的區別)

實際上,編譯器是否優化了一個方法(使實例方法是靜態的)並不重要 - 除非已經實例化方法,否則不會調用實例方法已經創建了實例,對吧?

在一天結束時,您應該嘗試優化代碼的可維護性,而不是試圖在這裏或那裏節省3納秒。

+0

我希望我們的C#編譯器像C++編譯器一樣足夠聰明,可以進行這種優化。感謝您的解釋! – viky 2009-12-14 07:19:11

0

是靜態方法很快,但靜態變量獲取的內存不受GC控制,即使不需要也不會釋放,所以這是一個問題。

但是比其他任何事情你都應該考慮通用性的設計,因爲內存和速度已經增加了幾天,但是如果你不適當地使用靜態變量,你的設計可能會很糟糕。

+0

您不需要有一個靜態變量來調用靜態方法。他們是不同的概念。 – 2009-12-15 01:11:52