调用 Int32 上的方法时发出 IL NullReferenceException
Emitted IL NullReferenceException on call to method on Int32
我是 .NET 中 IL 的新手,正在尝试自动生成纯样板文件的方法。
我的测试应用程序生成以下 IL,但它在 IL_002f
处抛出 NullReferenceException为 NULL(通过 IL (IL_0001
) 和我生成的测试用例)。该实例在第一个参数 (arg.0
) 中传递给发出的方法。
我希望 BasicClass.IntProperty
的值是调用 System.Int32.ToString()
之前堆栈中的第一项,那么这里可能出了什么问题?如果能帮助我摆脱我的 ahem 的困扰,我们将不胜感激。
IL_0000: ldarg.0
IL_0001: brfalse IL_0045
IL_0006: ldarg.0
IL_0007: call System.String get_StringProperty()/QuickSearchTests.Entities.BasicClass
IL_000c: dup
IL_000d: brfalse IL_0022
IL_0012: ldarg.1
IL_0013: call Boolean ContainsIgnoreNull(System.String, System.String)/MyCompany.MyProduct.Common.Extensions.StringExtensions
IL_0018: brtrue IL_0047
IL_001d: br IL_0023
IL_0022: pop
IL_0023: ldarg.2
IL_0024: brfalse IL_0045
IL_0029: ldarg.0
IL_002a: call Int32 get_IntProperty()/QuickSearchTests.Entities.BasicClass
IL_002f: call System.String ToString()/System.Int32
IL_0034: ldarg.1
IL_0035: call Boolean ContainsIgnoreNull(System.String, System.String)/MyCompany.MyProduct.Common.Extensions.StringExtensions
IL_003a: brtrue IL_0047
IL_003f: br IL_0045
IL_0044: pop
IL_0045: ldc.i4.0
IL_0046: ret
IL_0047: ldc.i4.1
IL_0048: ret
供参考,这里是BasicClass
的定义
public class BasicClass
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
internal string InternalStringProperty { get; set; }
}
您正在对非对象调用方法:整数值需要装箱才能使方法调用起作用。我会这样修补你的代码(Z 是你的选择):
.locals
[Z] int32 temp
callvirt instance int32 QuickSearchTests.Entities.BasicClass/BasicClass::get_IntProperty()
stloc.Z
ldloca.s temp
call instance string [System.Runtime]System.Int32::ToString()
一句警告:直接编写 IL 是一件特别具有挑战性的事情。您必须知道,一旦您的 IL 代码按预期工作,您还没有完成,因为您应该使用 peverifyverify 它。有效的 IL 无法自动验证。
因此,正如评论中所建议的,最好的方法是研究文档并向一位非常特殊的老师学习:编译器。从使用支持的语言编写代码开始,了解编译器如何转换为 IL。
我是 .NET 中 IL 的新手,正在尝试自动生成纯样板文件的方法。
我的测试应用程序生成以下 IL,但它在 IL_002f
处抛出 NullReferenceException为 NULL(通过 IL (IL_0001
) 和我生成的测试用例)。该实例在第一个参数 (arg.0
) 中传递给发出的方法。
我希望 BasicClass.IntProperty
的值是调用 System.Int32.ToString()
之前堆栈中的第一项,那么这里可能出了什么问题?如果能帮助我摆脱我的 ahem 的困扰,我们将不胜感激。
IL_0000: ldarg.0
IL_0001: brfalse IL_0045
IL_0006: ldarg.0
IL_0007: call System.String get_StringProperty()/QuickSearchTests.Entities.BasicClass
IL_000c: dup
IL_000d: brfalse IL_0022
IL_0012: ldarg.1
IL_0013: call Boolean ContainsIgnoreNull(System.String, System.String)/MyCompany.MyProduct.Common.Extensions.StringExtensions
IL_0018: brtrue IL_0047
IL_001d: br IL_0023
IL_0022: pop
IL_0023: ldarg.2
IL_0024: brfalse IL_0045
IL_0029: ldarg.0
IL_002a: call Int32 get_IntProperty()/QuickSearchTests.Entities.BasicClass
IL_002f: call System.String ToString()/System.Int32
IL_0034: ldarg.1
IL_0035: call Boolean ContainsIgnoreNull(System.String, System.String)/MyCompany.MyProduct.Common.Extensions.StringExtensions
IL_003a: brtrue IL_0047
IL_003f: br IL_0045
IL_0044: pop
IL_0045: ldc.i4.0
IL_0046: ret
IL_0047: ldc.i4.1
IL_0048: ret
供参考,这里是BasicClass
public class BasicClass
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
internal string InternalStringProperty { get; set; }
}
您正在对非对象调用方法:整数值需要装箱才能使方法调用起作用。我会这样修补你的代码(Z 是你的选择):
.locals
[Z] int32 temp
callvirt instance int32 QuickSearchTests.Entities.BasicClass/BasicClass::get_IntProperty()
stloc.Z
ldloca.s temp
call instance string [System.Runtime]System.Int32::ToString()
一句警告:直接编写 IL 是一件特别具有挑战性的事情。您必须知道,一旦您的 IL 代码按预期工作,您还没有完成,因为您应该使用 peverifyverify 它。有效的 IL 无法自动验证。
因此,正如评论中所建议的,最好的方法是研究文档并向一位非常特殊的老师学习:编译器。从使用支持的语言编写代码开始,了解编译器如何转换为 IL。