【问题标题】:Do both of these constructors do the same thing?这两个构造函数都做同样的事情吗?
【发布时间】:2014-09-30 16:30:51
【问题描述】:

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

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
}

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

【问题讨论】:

标签: c# static-constructor


【解决方案1】:

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

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

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

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

【讨论】:

  • 当两个选项都可能时,您通常更喜欢哪一个,有或没有静态构造函数定义?
  • @LucaCremonesi:通常我会选择更清晰的那个 - 通常没有静态构造函数,除非我在初始化中做了大量工作(这通常是一种设计味道) .
【解决方案2】:

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

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

【讨论】:

  • 不完全是:当有一个静态构造函数时,它就在调用构造函数或任何静态成员之前。当没有静态构造函数时,它在对 static 字段的任何访问之前 - 使用实例字段不必触发初始化程序。
【解决方案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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-04
      • 1970-01-01
      • 2011-06-15
      • 1970-01-01
      • 2012-09-08
      • 1970-01-01
      • 2021-12-25
      • 2013-06-26
      相关资源
      最近更新 更多