静态字段初始化程序有时会在Application_start之前运行

Whi*_*ght 5 asp.net

我有一个ASP.NET Web应用程序,它开始显示一些非常奇怪的行为.这是一些示例代码:

// in Bar.cs
public class Bar {
    public static Baz baz = Something.Step2();
}

// in Global.asax
public void Application_Start(...) {
    Something.Step1();
}
Run Code Online (Sandbox Code Playgroud)

故事的简短版本是这样的:在某些机器上,Something.Step2在Something.Step1之前执行并且抛出一个不可处理的异常.在其他计算机上,Step1在Step2之前正确执行.Global.asax及其使用的所有对象根本不涉及Bar.

什么时候静态字段应该相对于其他编程元素执行?为什么两台机器(Win7 64位,包括.NET 4.0,相同的IIS版本等)以不同的顺序执行操作?订单在每台机器上也是一致的.在我的机器上,它总是在Step1之前执行Step2,但是在我的同事的机器上它总是在Step2之前执行Step1.

非常感谢帮助.

更新我找到了访问我的静态字段的根本原因.我的示例中的"Bar"类实际上是一个自定义身份验证模块,并在web.config中作为System.webServer下的Authentication处理程序引用.如果我从web.config中删除该行,我的系统首先调用Step1,从不调用Step2.我的问题巧妙地改为:"为什么web.config导致我的静态初始化器被触发,为什么它会在Application_Start执行之前触发它们?"

Ree*_*sey 7

当您没有静态构造函数时,静态字段初始值设定项在第一次访问之前的"依赖于实现"时间初始化.这意味着它们可以随时初始化 - 您不能依赖于Bar.Baz第一次使用时的初始化Bar.

添加一个静态构造函数Bar会改变它的行为,使其更符合您的期望.

有关详细信息,请阅读C#语言规范10.5.5.1节:

10.5.5.1静态字段初始化

类的静态字段变量初始值设定项对应于以它们出现在类声明中的文本顺序执行的赋值序列.如果类中存在静态构造函数(第10.12节),则在执行该静态构造函数之前立即执行静态字段初始值设定项.否则,静态字段初始化器在第一次使用该类的静态字段之前的实现相关时间执行.

另请参见10.2,有关静态构造函数的详细信息:

封闭类类型的静态构造函数在给定的应用程序域中最多执行一次.静态构造函数的执行由应用程序域中发生的以下第一个事件触发:

·创建类类型的实例.

·引用类类型的任何静态成员.

话虽这么说,如果需要确定性初始化,我强烈建议添加静态构造函数Something,并在那里正确进行初始化.除了在这种情况下提供初始化顺序的保证之外,它还将阻止Something另一个类的使用导致您的代码在将来中断.