日期:2014-05-18  浏览次数:21129 次

field 采用 new XX() 来初始化(定义时赋值),每个 ctor 都会有这个 new 语句吗?
根据 Jeff 的书中所讲,field 定义时采用赋值形式初始化,这些初始化代码实际上是在 ctor 中完成的。有多少个 ctor ,将会有多少份初始化代码。
如下面的代码所示,InnerObject innerObject = new InnerObject() 将会出现在 ctor 中。而且 class Foo 有两个 ctor, 于是在这两个 ctor 中将会出现相同的两行代码。这是我对 Jeff 书中描述的理解。
今天我特意写了一个试验程序,用来验证 Jeff 所说。结果出乎意料。当我使用 Foo(int a) 构造函数构造对象时,InnerObject 的 ctor 只被调用了一次。这是为什么呢?预期中的,应该是两次。因为 Foo(int a) 调用了 Foo()。 难道编译器做了优化?

C# code

    public class InnerObject
    {
        public InnerObject()
        {
            Debug.WriteLine("InnerObject() ctor");
        }
    }

    public class Foo
    {
        private InnerObject innerObject = new InnerObject();

        public Foo()
        {
        }

        public Foo(int a) : this()
        {
        }
    }

    // 然后我在应用程序的初始化函数中构造一个 Foo
    Foo foo = new Foo(2);



------解决方案--------------------
这个就的佩服VS编译器了。

你把
public Foo(int a) : this()
{
}
中调用无参构造函数去掉:
public Foo(int a)
{
}

你会发现编译器在Foo(int a)中插入了innerObject的初始代码:
.method public hidebysig specialname rtspecialname 
instance void .ctor(int32 a) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void InnerObject::.ctor() //<-----
IL_0006: stfld class InnerObject Foo::innerObject
IL_000b: ldarg.0
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: ret
}

而当Foo(int a)调用无参构造函数的时候,编译器则聪明到不在Foo(int a)中初始化innerObject,
只在无参构造函数中初始化innerObject。