而實際情況則是:
// 實際的順序
BaseConstructor()
{
baseFoo = new Foo("Base initializer");
ObjectConstructor();
Console.WriteLine("Base constructor");
}
DerivedConstructor()
{
derivedFoo = new Foo("Derived initializer");
BaseConstructor();
Console.WriteLine("Derived constructor");
}
那麼,這樣處理是為什麼呢?
...
...
...
我們來看一下,如果代碼按期望的順序(第一段偽代碼)執行,會產生什麼問題:
class Base
{
public Base()
{
Console.WriteLine("Base constructor");
if (this is Derived) (this as Derived).DoIt();
// 如果是在創建Derived類的實例,就會遭遇null。
Blah();
// 如果是在創建MoreDerived類的實例,就會遭遇null。
}
public virtual void Blah() { }
}
class Derived : Base
{
readonly Foo derivedFoo = new Foo("Derived initializer");
public DoIt()
{
derivedFoo.Bar();
}
}
class MoreDerived : Derived
{
public override void Blah() { DoIt(); }
}
看Base類的構造函數,如果按期望的順序執行,那麼在Base方法執行時,Derived類的實例成員並沒有得到初始化,此時就會有NullReference異常了。
而按照實際執行的順序,所有的實例成員都能確保被完整地初始化:)
當然了,如果readonly字段是在構造函數中進行的,那麼上面的確保機制就不復存在了