2010-05-27 30 views
11

從以下程序的輸出是:靜態構造函數可以在非靜態構造函數之後運行。這是一個編譯器錯誤?

Non-Static 
Static 
Non-Static 

這是一個編譯器錯誤?我的預期:

Static 
Non-Static 
Non-Static 

因爲我認爲靜態構造函數在非靜態構造函數之前總是被調用。

我使用.net 3.5和.net 4.0對Visual Studio 2010進行了測試。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace StaticConstructorBug 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var mc = new MyClass(); 

      Console.ReadKey(); 
     } 
    } 

    public class MyClass 
    { 
     public MyClass() 
     { 
      Console.WriteLine("Non-static"); 
     } 

     static MyClass() 
     { 
      Console.WriteLine("Static"); 
     } 

     public static MyClass aVar = new MyClass(); 
    } 
} 
+0

你能解釋爲什麼你預期?因爲這不是說明書所期望的。 – 2010-05-27 23:30:53

回答

11

參見ECMA 334§17.4.5.1:

17.4.5.1靜態字段初始化

的靜電場變量初始化類聲明的 對應於是 在執行任務的 序列其中 它們出現在類聲明中的文本順序。 如果該類中存在靜態構造方法(§17.11) ,則在執行該靜態構造方法之前立即執行 靜態字段初始值設定項 。否則, 靜態字段初始化器 第一次使用該類的靜態 字段

具體的之前執行 在與實現相關的時間:「靜態字段初始的執行發生之前立即執行那個靜態構造函數「。

你的static MyClass aVar必須在你的靜態構造函數執行之前被初始化(或者至少它必須以這種方式出現)。沒有那個靜態成員,應該在任何非靜態構造函數之前調用靜態構造函數。

如果你仍然想要一個MyClass單身人士,你可以把它放在一個容器類中並使用它來引用它,例如,:

public static class MyClassSingleton 
{ 
    public static MyClass aVar = new MyClass(); 
} 
1

public static MyClass aVar = new MyClass();是您的靜態構造函數的一部分。如果你用反光鏡看它,你會看到以下內容:

static MyClass() 
{ 
    aVar = new Program.MyClass(); 
    Console.WriteLine("Static"); 
} 

所以你的結果現在應該是明顯的。

0

從MSDN Link

靜態構造函數被調用 一審之前自動初始化類 創建 或任何靜態成員被引用。

我猜猜這是因爲在最後一行實例的靜態實例,但根據MSDN靜態構造函數應該發生在第一個實例被調用之前。

+0

是的 - 所以靜態構造函數被調用,它初始化數據成員(用正常的構造函數構造),然後控制返回到用戶定義的靜態構造函數,在那裏他打印出行。 – Puppy 2010-05-27 23:12:30

5

它是由行public static MyClass aVar = new MyClass();引起的。

事實上,aVar = new MyClass();是前置於靜態構件。所以,你的靜態構造函數:

static MyClass() { 
    Console.WriteLine("Static"); 
} 

改爲:

static MyClass() { 
    aVar = new MyClass(); // this will run instance contstructor and prints "Non-Static" 
    Console.WriteLine("Static"); 
}