2010-08-26 124 views
6

預計輸出&輸出我得到在調試模式下,和VS2010下釋放模式,.NET 4.0:靜態成員變量未在Release - Compiler/clr bug中初始化?

bar construct 
main 

輸出在釋放模式 VS2010的調試器,並且在WinDbg中:

main 

程序並未表現出對VS2005這種行爲,.NET 2.0

using System; 

namespace static_init 
{ 
    public class bar 
    { 
     public bar() 
     { 
      Console.WriteLine("bar construct"); 
     } 
    } 

    class Program 
    { 
     public static bar blah = new bar(); 

     static void Main(string[] args) 
     { 
      Console.WriteLine("main"); 
      Console.ReadLine(); 
     } 
    } 
} 

可能與: Static constructor can run after the non-static constructor. Is this a compiler bug?

更新

在我實際的代碼,構造函數初始化bar()一些互操作代碼C++(非託管)。它需要發生在這個庫的其他任何東西之前 - 是否有任何方法可以確保沒有在庫中加入一個涉及所有靜態(帶有不在外部引用的副作用)的函數?

對於未來的搜索者的注意事項:我正在使用SWIG,並且這是他們在包裝生成代碼中做出的假設。 SWIGStringHelper是目前的罪犯,可能會有更多。

結論

更新痛飲的2.0版本,需要通過.NET的新版本它把在靜態構造函數。

+0

非常感謝'更新'和'結論' - 我有非常相似的場景,也使用舊的SWIG 1.3.40 - 只是更新到2.0.9,一切正常。 「結論」爲我節省了大量時間! – sergtk 2013-03-13 21:28:29

回答

10

它可能會被優化,因爲你不使用它。

它也不是編譯器錯誤,它在語言規範中。

17.4.5.1靜態字段初始化

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

因爲你從來不使用程序類的靜態字段的靜態 場之前執行 以實現相關的時間 ,不保證靜態初始化器運行(儘管它可以...在「實現相關的時間」以上)

更新
您可以通過程序完成你想要有一個靜態構造函數。

static Program(){} 或可能通過訪問另一個(可能是假的)靜態變量

6

注意,已經有關於靜態初始化一些變化在.NET 4.0中。喬恩斯基特寫了一個博客帖子有一些樣品:

Type initialization changes in .NET 4.0

如果你想精確的初始化,你應該使用一個靜態構造函數(可能爲空)。

using System; 

namespace static_init 
{ 
    public class bar 
    { 
     public bar() 
     { 
      Console.WriteLine("bar construct"); 
     } 
    } 

    class Program 
    { 
     public static bar blah = new bar(); 

     // This static constructor will make sure that the type Program 
     // is initialized before it is first used. 
     // 
     static Program() 
     { } 

     static void Main(string[] args) 
     { 
      Console.WriteLine("main"); 
      Console.ReadLine(); 
     } 
    } 
}