C#何时设置具有默认值的实例变量?

时间:2010-02-01 02:51:13

标签: c#

我一直想知道这一点。在C#中,何时设置具有默认值的实例变量 - 在构造函数之前或之后?

对于此代码:

public class Foo
{
  public int bar=1;
  public Foo()
  {
    bar = 2;
  }
}
...
Console.WriteLine(new Foo().bar);

输出1还是2?

7 个答案:

答案 0 :(得分:4)

构造期间的实例将首先遍历所有声明,然后进入构造函数本身。

因此,bar = 1将在bar = 2之前执行,但最终结果仍为bar = 2。

答案 1 :(得分:1)

它将返回2,您在构造函数修改后访问该属性。

答案 2 :(得分:1)

成员实例化首先在构造函数中添加。如果你查看使用Reflector实际创建的IL代码,这就是编译器用它做的事情:

.class auto ansi nested public beforefieldinit Foo
  extends [mscorlib]System.Object
{
  .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
  {
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: ldc.i4.1 
    L_0002: stfld int32 Test.Program/Foo::bar
    L_0007: ldarg.0 
    L_0008: call instance void [mscorlib]System.Object::.ctor()
    L_000d: nop 
    L_000e: nop 
    L_000f: ldarg.0 
    L_0010: ldc.i4.2 
    L_0011: stfld int32 Test.Program/Foo::bar
    L_0016: nop 
    L_0017: ret 
  }

  .field public int32 bar

}

因此,成员实例化首先放在构造函数中,然后调用基类型的构造函数,然后是你在构造函数中放入的代码。

答案 3 :(得分:1)

答案 4 :(得分:0)

你为什么不测试这个?

实例化类对象时,实质上是创建类的实例,然后运行构造函数。因此,它应输出2

答案 5 :(得分:0)

在调用构造函数之前,底层字节码没有任何特殊的能力来初始化这些值。 C#编译器负责排序,它在类型为.ctor的方法中以字节码形式发出:

如果构造函数没有将this(...)指定为链式构造函数,意味着它指定base(...)或者根本不指定任何内容,那么它就是:

  1. 使用初始化程序设置所有字段的值。
  2. 调用基类的构造函数。如果未指定特定的一个,则调用默认值。
  3. 运行您在构造函数中输入的代码。
  4. 如果构造函数将this(...)指定为链式构造函数,则顺序略有不同,因为链式构造函数将处理字段的初始化。

    1. 调用链式构造函数,该构造函数是您使用: this(...)明确指出的构造函数。
    2. 运行您在构造函数中输入的代码。

答案 6 :(得分:0)

如果没有发生这种情况,可能会造成一些非常令人困惑和不直观的情况。就像构造函数中的某些东西以某种特定的方式取决于bar的初始值一样,它不知道它是否已被初始化(或者更糟糕的是,bar是用户定义的类而不是int。是否为null因为构造函数该课程希望它是什么?还是只是没有被初始化?) 它有助于将构造函数视为你阶级的诞生过程,就像婴儿实际上从它的木乃伊中弹出一样,并初始化为子宫中的成长。 初始化等前提条件是给定的 - 你不会看到一个没有武器出生的婴儿,然后突然他们出现一小时后你会吗?