我剛剛花了幾個小時被NullReferenceException
弄糊塗了,我認爲那裏不應該有一個。我正在建造的一類,像這樣:爲什麼我們需要在MSIL中顯式調用父構造函數?
public class MyClass : MyBase<Foo>
{
public MyClass()
{
base.Method(Foo.StaticField);
}
}
其中
public class MyBase<T>
{
private SomeObject bar = new SomeObject();
public void Method(object o)
{
this.bar.AnotherMethod(o); // exception thrown here
}
}
基本上我的IL是以下幾點:
ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Ldsfld, staticField);
ctorIl.Emit(OpCodes.Box, typeof(FieldType));
ctorIl.Emit(OpCodes.Call, parentMethod);
ctorIl.Emit(OpCodes.Ret);
,我終於想通它必須是bar
沒有被實例化。我構建了我的類在C#中並編譯了一下,發現唯一的區別是,下面應該是IL上述上面:
ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Call, parentCtor);
// as above
有了這些行,我的代碼現在將按預期。
所以我的問題是:
- 爲什麼我們需要顯式調用基類的構造實例字段?
- 有沒有調用基礎構造函數的合法用法?
- ...如果沒有,爲什麼CLR接受它作爲一個有效的程序?
@PatrickHofman最佳編輯有史以來:P – 2014-09-11 13:15:42
基類構造函數是**總是**被調用。如果你沒有在你的C#代碼中明確寫出它,那麼編譯器會爲你做。 * *注意總是有一個,System.Object有一個構造函數。使用ildasm.exe很容易看到,在開始生成自己的MSIL之前,您始終需要使用該工具。 – 2014-09-11 13:21:11
@HansPassant在C#中是的,是的;在IL中:並非如此 – 2014-09-11 13:22:01