这两个构造函数都做同样的事情吗?

时间:2014-09-30 16:30:51

标签: c# static-constructor

这两个代码块都做同样的事情吗?

class A {
   public static int s;
   A(){}
   static A(){s = 100;}
}

class A {
   public static int s=100;
   A(){}
   //static A(){s = 100;} do not use
}

他们做同样的事情吗?我想是的。

4 个答案:

答案 0 :(得分:11)

不,他们的行为方式不一样。如果没有静态构造函数,那么类型初始化程序执行时的确切时间会更加宽松 - 它可能会比您预期的更早发生或更晚

当有静态构造函数时,类型初始值设定项会在首次使用类型时执行任何正在访问的静态成员或正在创建的任何实例。

不是静态构造函数时,唯一的保证是初始化程序将在第一次访问静态字段之前的某个时刻执行(并且仍然只执行一次)。取决于JIT,这可能意味着它很早就被执行(例如,当您第一次执行可能使用成员的方法时)或非常晚(调用之后)静态成员,不使用任何字段,或创建和使用实例后。)

在IL中,不同之处在于没有静态构造函数的类型具有beforefieldinit标志;一个有静态构造函数的人没有。

答案 1 :(得分:4)

效果是相同的,但实际执行顺序可能不同。当存在静态构造函数时,在调用构造函数或访问任何静态字段之前立即初始化静态字段。如果没有静态构造函数,则可以在第一次使用其中一个静态字段之前的任何时间执行字段初始值设定项。

由于您的初始化程序没有副作用且无法抛出异常,因此除非使用反射或其他一些外部观察者(例如调试程序),否则两者之间不会有任何可辨别的差异

答案 2 :(得分:3)

除了某些边缘情况,例如beforefieldinit行为,是,他们做同样的事情。事实上,在两种情况下编译的IL几乎相同。唯一的区别是没有静态构造函数的情况下存在beforefieldinit

class A
{
    public static int s;
    A() { }
    static A() { s = 100; }
}

class B
{
    public static int s = 100;
    B() { }
}

编译为......

.class private auto ansi A
    extends [mscorlib]System.Object

.class private auto ansi beforefieldinit B
    extends [mscorlib]System.Object

使用相同的方法/字段定义。

答案 3 :(得分:0)

根据Nutshell中的 C#,首次使用该属性时会执行静态构造函数,并且最常用的是当您想要计算或读取某些数据并设置为静态时property (类似于appconfig.config中的密码)。如果不使用静态构造函数,则必须定义Init方法,并在应用程序启动时调用它。