为什么我们需要在 MSIL 中显式调用父构造函数
本文关键字:调用 构造函数 MSIL 我们 为什么 | 更新日期: 2023-09-27 18:21:28
我只是花了几个小时被一个我认为不应该有的NullReferenceException
弄糊涂了。我正在构建一个这样的类:
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 接受它作为有效程序?
- 因为它不是自动的,并且它允许编译器和 IL 代码决定何时以及是否调用基构造函数
- 好吧,您实际上可以在不使用任何构造函数的情况下实例化类型......边缘情况,当然;但允许
- 因为它是允许的
请注意,您实际上可以在单个方法中发出一个简单的构造函数(包括基调用(:
typeBuilder.DefineDefaultConstructor();