2010-02-27 170 views
19

如何C#或其他語言對於這個問題,處理這兩種情況之間的內存分配(和內存重新分配):C#類實例的靜態方法VS靜態類的內存使用情況

1)上的方法一個靜態類被調用。

public Program { 
    Foo foo = Loader.load(); 
} 

public static Loader { 
    public static Foo load() { 
     return new Foo(); 
    } 
} 

2.)在實例上調用一個方法,然後該方法超出範圍。

public Program { 
    Foo foo = new Loader().load(); 
} 

public Loader { 
    public Foo load() { 
     return new Foo(); 
    } 
} 

我想靜態類是加載,並保留在內存中;而類實例在C#閒暇時屈服於垃圾收集。這兩種範式有什麼優點或缺點?是否有一段時間你有一個永遠不需要實例化的類(即某種資源加載器或工廠),但是你仍然使用第二種方法來利用垃圾收集?

我的問題的最重要的部分是,是否第一範式,同時在某些情況下,概念正確,可能不必要地抓着記憶受損。

+3

第二個例子對我來說似乎不正確。調用一個靜態方法需要一個以類名作爲前綴。例如'Loader.Load()'&** not **'new Loader()。Load()' – shahkalpesh 2010-02-27 17:55:09

+0

你是對的,Shah - 你不需要一個實例來調用靜態方法。這是有點:) – 2010-02-27 18:14:05

+0

啊,你們是對的,謝謝,我已經改寫它,以瞭解我試圖問的問題的肉。 – jtb 2010-02-27 18:30:56

回答

8

你的第二個例子是不行的,所以讓我們來看看真正的選擇:

1)的靜態類中的方法被調用。

public Program { 
    Foo foo = Loader.Load(); 
} 

public static Loader { 
    public static Foo Load() { 
     return new Foo(); 
    } 
} 

2.)調用非靜態類中的靜態方法。

public Program { 
    Foo foo = Loader.Load(); 
} 

public Loader { 
    public static Foo Load() { 
     return new Foo(); 
    } 
} 

3.)的實例方法被調用上的一個實例

public Program { 
    Foo foo = new Loader().Load(); 
} 

public Loader { 
    public Foo Load() { 
     return new Foo(); 
    } 
} 

兩個第一是相同的。無論類是否爲靜態,調用靜態方法都是一樣的。

第三個選項將在堆上創建的類的實例。由於該類沒有數據成員,因此它只會是16個字節。它最終會被垃圾收集,但由於體積小,發生這種情況並不重要。

調用實例方法也是從一個靜態方法略有不同。一起發送對類實例的引用,您可以通過this關鍵字進行訪問。這種情況幾乎沒有什麼區別,因爲對象中沒有真正的數據可以訪問。

+0

當一個對象的實例被垃圾回收(顯然除了實例字段數據)之外,C#程序的內存佔用是否會發生變化,是否曾經有卸載過的類型信息?通俗地講,C#會執行任何優化,比如「哦,這些類中沒有任何一個實例,我不再需要它們,我將從程序中卸載原始類型數據並保存一些內存「? – jtb 2010-02-27 18:50:54

+0

@jtb:不,據我所知.NET不會卸載曾經加載過的程序集。 – Guffa 2010-02-27 19:43:17

+0

@jtb只有在沒有引用/句柄等並且只有在操作系統內存資源稀少的情況下,GC纔會釋放您的類佔用的內存。 – 2012-06-14 16:53:33

1

靜態方法,字段,屬性或事件上,即使已創建無類的實例類調用。

http://msdn.microsoft.com/en-us/library/79b3xss3(VS.80).aspx

因此,在這個意義上說你的靜態方法的行爲就像它,如果你從一個類的實例中使用它:它的作用範圍是類型。

+0

是啊,我的榜樣遭受了寫得不好的問題來說明我的問題。我不知道這是否合適,因爲你是正確的,但爲了提出我真正想問的問題,我將不得不輕輕地重述一下我的問題。 – jtb 2010-02-27 18:20:15

+0

鑑於靜態成員的範圍是該類型,因此我認爲內存使用情況不會因爲您在該類型的實例中調用而改變。 – 2010-02-27 18:25:59

1

第二種形式創建臨時Loader對象(它是很便宜)。無論您選擇哪種方法,您都必須加載Loader類。

很少有表現(內存保存)在這裏獲得。如果在方法局部變量之外不需要「狀態」,通常會選擇靜態類中的靜態成員。

+0

@亨克:第二個例子不會在c#中編譯。對? – shahkalpesh 2010-02-27 18:03:15

+0

@Shah它會編譯。注意第二個示例不調用靜態方法!它正在調用一個正常的公共方法,然後再進行垃圾收集,因爲它永遠不會再被引用。 – 2010-02-27 18:33:34

+0

是的,人們感到困惑,因爲我原來的帖子在第二個例子中標記爲靜態的方法,我編輯它。 – jtb 2010-02-27 18:59:58

0

我找不到這方面的任何來源,但是從我的節目,當你refernce類(非靜態)的知識,它的結構被加載到內存

創建類的實例只是調用一個方法,會浪費很多處理能力(由於創建實例,分配內存和垃圾收集)。

而不是保持定義,然後在它的頂部,一個實例。爲什麼不保留定義(靜態)。

只要您不在靜態變量中存儲任何數據,您的靜態方法應該佔用與非靜態方法定義相同的內存量。但是使用靜態方法,只有方法會被保存在內存中,並隨時可以隨時調用,而無需創建實例。如果方法是非靜態的,它將需要實例化(使用內存和處理能力)和收集的垃圾(釋放內存並使用cpu),因此使用靜態成員肯定會更好。那就是他們在那裏。

+0

當首先引用靜態類時,我的理解是C#運行靜態初始化程序,將靜態字段加載到內存中,並將類型數據(類結構)加載到內存中,並在程序運行時保持它。 當創建一個類的實例時,處理構造函數,爲實例字段分配內存,並將類型數據加載到內存中(如果它已經不存在)。然而,當一個類的實例離開作用域時,它的數據最終會被遺傳給ether,但是Type數據是否被釋放? – jtb 2010-02-27 19:17:16

相關問題