2010-08-26 80 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(); 
     } 
    } 
}