2009-07-26 215 views
29

假設您有一些方法可以在非靜態類中進行靜態化。
例如:靜態與非靜態方法

private double power(double a, double b) 
    { 
     return (Math.Pow(a, b)); 
    } 

你看到從改變方法的簽名爲靜態任何好處?在上面的例子:

private static double power(double a, double b) 
    { 
     return (Math.Pow(a, b)); 
    } 

即使有一些性能或記憶的增益,不會編譯器做在編譯時一個簡單的優化?


編輯:我在尋找的是通過聲明方法爲靜態的好處。我 知道,這是常見的做法。我想了解它背後的邏輯。
當然,這種方法只是一個例子來闡明我的意圖。

+0

@大家好,我知道這是發展年代的一個「古老」問題,但它今天仍然相關。下面有很多**優秀的**答案。需要您的特定場景的實際性能數字?編寫一個快速的程序,調用該方法足夠多的時間(在var start = DateTime.Now()和var end = DateTime.Now()之間),以便能夠經歷足夠長的時間以進行比較。用`static`運行幾次,沒有`static`運行幾次並比較差異。也許打開TaskManager並觀察每個場景的內存使用情況。 – 2014-11-25 15:12:21

+0

只是爲了完整性,而不是比較兩個`DateTime.Now()`之間的差異,請使用[`StopWatch`類](https://msdn.microsoft.com/zh-cn/library/system.diagnostics。秒錶(v = vs.110)的.aspx)。 編輯 - 爲什麼?它比'DateTime.Now()`方式更準確,更易於使用。 – 2015-11-18 09:44:06

回答

7

請注意,編譯器甚至不允許代表您進行更改,因爲它會更改方法的簽名。因此,一些精心製作的反射(如果你使用的話)可能會停止工作,編譯器真的不知道是否是這種情況。

1

這種方法應該是靜態的,因爲它是不相關的類或類成員。它只是與這個函數的輸入一起工作。

也許您可能需要在不創建該類的情況下調用它。所以如果它是靜態的,那麼可以,但如果不是這樣,你不能在沒有該類的任何實例的情況下調用它。在靜態方法


優點:

沒有必要先創建一個對象。該方法立即可用。

這是一個很好的,當你有一個不依賴於特定對象的狀態一般功能。例如,查看Arrays類或java.util的Collections類。

靜態方法對工廠很有用。將您的需求作爲參數傳遞,獲得一個全新的對象。看不到構造函數。

靜態方法的缺點:

你沒有一個對象實例,所以你只能訪問靜態成員和自己的局部變量。如果你想要一個實例,你可能必須自己創建它。

您可以創建子類,但靜態方法不能是抽象的,所以這是很難從呼叫者解耦實現。


(PS:我不認爲編譯器會優化它是否將是靜態的或不..但不知道)

33

根據定義,power是無狀態的,並且對任何封閉類無副作用所以應該聲明爲static

article從MSDN進入一些非靜態與靜態的性能差異。這個調用比實例化和調用快四倍,但它確實只是一個嚴格的循環,這是一個性能瓶頸。

+0

鏈接在哪裏? – 2009-07-26 14:32:46

+0

@niko:修正。對不起,謝謝。 – jason 2009-07-26 14:33:23

+0

爲msdn鏈接+1。 – 2009-07-26 15:34:22

2

要我一個容易回答的決定是「我應該實例化這個對象只是調用該函數」。在你的功能的情況下,我會說答案是否定的,所以它應該是靜態的。這個方法似乎沒有關係到你的對象,所以我再次投票靜態。

8

如果您將方法聲明爲靜態,應該會有輕微的性能改進,因爲編譯器將發出call IL指令而不是callvirt

但像其他人說,這應該是靜態的,無論如何,因爲它不涉及具體的實例

0

我相信,編譯器不會優化成一個靜態方法這一點。性能提高了,因爲不需要檢查指針是否在運行時爲空。看看FXCop rule以供參考。

1

編譯器可能會考慮在它將代碼「JITs」縮短的情況下進行內聯,如果這樣做的話,那麼很可能會優化對未使用的此參數的引用。但是你不能依賴任何這些。

你仍然需要創建一個對象才能調用它,除非將其設置爲static,否則如果因爲其他原因而不需要其中一個,則會有更大的開銷。

-5

我希望我們需要定義靜態和非靜態方法之間的區別。在這裏,我發佈了幾行簡單的代碼來形象化概念差異。

public class StaticVsNonStatic 
{ 
    public string NonStaticMethod() //non-static 
    { 

     return "I am the Non-Static Method"; 

    } 

    static public string StaticMethod() //static 
    { 

     return "I am Static Method"; 
    } 

} 

現在讓我們創建一個aspx頁面,嘗試訪問這兩個類中定義的方法。

public partial class StaticVsNonStatic_StaticVsNonWorkplace : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 

     StaticVsNonStatic objStaticVsNonStatic = new StaticVsNonStatic(); 
     lblDisplayNS.Text = objStaticVsNonStatic.NonStaticMethod(); //Non Static 
     lblDisplayS.Text = StaticVsNonStatic.StaticMethod(); //Static and called without object 
    } 
} 

謝謝,請發表評論。

最好的問候,Pritom南迪[孟加拉國]

2

不訪問實例數據或調用實例方法成員可以被標記爲靜態的(在Visual Basic中共享)。將這些方法標記爲靜態後,編譯器將向這些成員發出非虛擬呼叫站點。發出非虛擬呼叫站點將阻止在運行時檢查每個呼叫,以確保當前對象指針非空。這可以爲性能敏感的代碼實現可衡量的性能提升。在某些情況下,訪問當前對象實例失敗表示正確性問題。

3

您是否發現將方法簽名更改爲靜態有任何好處?

三個好處:

  1. 製造無國籍方法靜態幫助文檔,並澄清自己的目的。否則,人們傾向於擔心該方法依賴於什麼神祕的狀態?

  2. 靜態方法可以從其他靜態代碼調用,因此可能更有用。

  3. 靜態方法調用比實例調用具有更少的運行時開銷。編譯器不能自動進行轉換 - 一個原因是因爲它會影響null的使用。即使在方法中沒有使用實例狀態,也需要在空引用上調用該方法以失敗並返回NullReferenceException。