4

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

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

4 回答 4

11

不,它们的行为方式并不完全相同。如果没有静态构造函数,类型初始值设定项执行的确切时间会宽松得多——它可能比您预期的更早或更晚发生。

当有一个静态构造函数时,类型初始化程序在第一次使用该类型时执行,就任何正在访问的静态成员或任何正在创建的实例而言。

没有静态构造函数时,唯一的保证是初始化器将在第一次访问静态字段之前的某个时间执行(并且仍然恰好一次)。根据 JIT,这可能意味着它执行得很早(例如,当您第一次执行可能使用成员的方法时)或很晚(调用不使用任何字段的静态成员之后,或者在创建和使用实例之后) .

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

于 2014-09-30T16:36:11.577 回答
4

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

由于您的初始化程序没有副作用并且不能抛出异常,因此两者不会有任何明显的区别,除非使用反射或其他一些外部观察者(例如调试器)

于 2014-09-30T16:37:06.293 回答
3

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

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

具有相同的方法/字段定义。

于 2014-09-30T16:37:26.073 回答
0

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

于 2014-09-30T16:47:13.497 回答