2009-11-26 66 views
13

兩個部分是:爲什麼靜態類不能有析構函數?

  1. 如果一個靜態類可以有靜態構造函數,爲什麼不能有一個靜態的析構函數?

  2. 什麼是最好的解決方法?我有一個靜態類來管理COM對象的連接池,如果程序中的其他地方出現問題,我需要確保它們的連接被關閉/釋放。

回答

18

而不是一個靜態類,你應該使用一個普通類與單例模式(即,你保持類的一個單一實例,可能由類本身的一個靜態屬性引用)。那麼你可以有一個析構函數,或者甚至更好,一個析構函數和Dispose方法的組合。

例如,如果你現在有:

static class MyClass 
{ 
    public static void MyMethod() {...} 
} 

//Using the class: 
MyClass.MyMethod(); 

你將不得不改爲:

class MyClass : IDisposable 
{ 
    public static MyClass() 
    { 
     Instance=new MyClass(); 
    } 

    public static MyClass Instance {get; private set;} 

    public void MyMethod() {...} 

    public void Dispose() 
    { 
     //... 
    } 

    ~MyClass() 
    { 
     //Your destructor goes here 
    } 
} 

//Using the class: 
MyClass.Instance.MyMethod(); 

(注意實例是如何在靜態構造函數,調用第一次創建任何類的靜態成員被引用)

+1

謝謝。我還在我的代碼中添加了一個私有的非靜態構造函數,因此該類不能在其他地方實例化。 –

+0

如果使用線程,則需要使代碼線程安全。 –

+1

這裏有一個很好的指導,介紹所有不同的方式來執行單線程模式與線程安全。 http://csharpindepth.com/Articles/General/Singleton.aspx – Naz

3

1.爲什麼? -類型不能像本質上通常考慮實例上的構造函數那樣擁有構造函數。通常,它有時被稱爲「靜態初始化器」方法,但Microsoft使用術語「類型構造器」(並且它有特殊的限制) - 您將代碼放入其中以初始化類型/類 - 如果它是一個實例構造器,它可能是超載。這種對「類型構造函數」的靜態限制是因爲.NET CLR負責在堆上加載類模板,並且不允許在這種情況下指定參數(因爲您將如何傳遞參數)。因爲從最嚴格的意義上說,程序員並不負責引起類型構造函數被調用,所以當程序員在CLR的域中更多時允許程序員編寫靜態析構函數是沒有多大意義的。 CLR最終將從堆中移除類模板,但類模板的生命週期比其實例長,因此無論如何您都不希望進行任何資源密集型操作(例如,保持打開數據庫連接)。

2.什麼? - Singleton 如果您遇到需要在類模板上打開資源並在之後銷燬它的情況,則可以考慮Singleton software pattern只有該類的一個實例,並且可能還實現了System.IDiposable接口除了析構函數之外,還有幫助清理。 (我看到有人已經先打我的IDisposable代碼示例,所以我會在這裏結束我的解決方案。)

7
  1. 靜態類沒有析構函數,因爲一個靜態類永遠不會被破壞。

  2. 如果你想創建和銷燬它的多個實例,它不應該是靜態的。讓它成爲一個完整的課程。

  3. 無論如何不應該使用析構函數來達到這個目的。使用IDisposable/Dispose。

+0

爲什麼編譯器允許你有一個? 'static〜ClassName(){}'它是否永遠不會運行? – Zapnologica

1

靜態類永遠不會被破壞。它與程序一起終止。您可以使用單例模式作爲實現,而不是使用靜態類

+0

您確定某個類(類型)沒有垃圾回收嗎? –

+0

@HenkHolterman是的。沒有什麼可收集的。由於所有的屬性/字段至少有一個引用(靜態類),並且由於靜態類的範圍是從第一次訪問直到程序終止,所以沒有任何東西可以收集 –

相關問題