2012-02-20 45 views
8

我偶然發現了一個問題,我需要在其靜態構造函數中的類的實例。我認爲這是不可能做到這一點,所以我嘗試了以下內容:一個類在靜態構造函數中創建自己的實例是否安全?

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine(Foo.someString); 
     Console.ReadLine(); 
    } 
} 

class Foo 
{ 
    public static readonly string someString; 

    static Foo() 
    { 
     someString = new Foo().CreateString(); 
    } 

    private string CreateString() 
    { 
     return "some text"; 
    } 
} 

令我驚訝的是,它的工作原理 - 輸出「一些文本」。我相信靜態構造函數必須在創建類的實例之前運行並完成。 This answer表明這不一定是這種情況。這是否意味着靜態和實例構造函數是相互獨立的?最後,是否安全(在靜態構造函數中創建實例)?

p.s.讓我們忽略這一事實,即可以通過使用不同的方法來避免這種情況。

回答

5

所有specification說的是靜態構造函數將在類的任何實例創建之前調用。但它沒有說明有關的事實,此構造必須完成什麼:

靜態構造函數用於初始化任何靜態數據,或 執行需要進行一次只能執行特定的操作。在創建第一個實例或引用任何 靜態成員之前,會自動調用它 。

你可以很好的在靜態構造函數中創建類的實例,這是安全的。

+0

取決於安全性的定義,實例化的位置和創建實例的用法 – 2012-02-20 09:55:34

+0

@Rune FS - 安全地執行與示例類似的操作 - 初始化靜態成員變量 – loodakrawa 2012-02-20 09:59:55

+0

靜態構造函數時要小心依賴於其他靜態構造函數。儘量不要獲得循環依賴,因爲這會導致您在靜態初始化器完成運行之前訪問成員並創建類的實例。框架不會爲此提醒你(即沒有例外或死鎖)。 – Ruben 2012-02-20 10:10:13

0

創建第一個實例之前自動調用的靜態構造函數或引用任何靜態成員的引用任何靜態字段。因此,當您的應用程序運行並且您訪問Foo時,靜態構造函數已執行並且您的字符串已初始化。

安全嗎?:因此,這樣做沒有任何傷害。它只是被執行一次而已。

有關此信息,請閱讀Static Classes and Static Class Members on MSDN

+0

Downvoter請提供理由。 – 2012-02-20 09:58:37

+0

首先靜態構造函數是在第一次訪問類型(成員)時調用的,而不是在加載包含類型的程序集時。其次,當上面調用靜態構造函數時,會創建一個實例,這是OP詢問安全與否的一個實例。因此,即使關於構造函數何時被調用的聲明它確實改變了OP在該特定時間實例化 – 2012-02-20 09:59:06

+0

不知道誰是downvoter,而是聲明「靜態構造函數在應用程序加載到內存中時調用」。是不正確的。 – Mentoliptus 2012-02-20 09:59:56

0

它是安全的,因爲它只會調用一次。

相關問題