Reputation: 554
I'm new to IL in .NET, and am messing around trying to autogenerate a method that is pure boilerplate.
My test app generates the below IL, but it is throwing a NullReferenceException at IL_002f
, after retrieving the value of an int
property on an instance which is known not to be NULL (both via the IL (IL_0001
) and from the test case I generated). The instance is passed in the first argument (arg.0
) to the emitted method.
I expect the value of BasicClass.IntProperty
to be the first item on the stack before calling System.Int32.ToString()
, so what is possibly going wrong here? Any help to get my head out of my ahem on this would be appreciated.
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
For reference, here is the definition of BasicClass
public class BasicClass
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
internal string InternalStringProperty { get; set; }
}
Upvotes: 0
Views: 78
Reputation: 6234
You are calling a method on a non object: the integer value needs to be boxed in order to have the method invocation work. I would patch your code this way (Z is your choice):
.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()
A word of warning: writing IL directly is something particularly challenging. You must be aware that once your IL code works as you expect, you have not finished yet, as you should verify it with peverify. Valid IL is not automatically verifiable.
For this reason, as suggested in the comment, the best approach is to study the documentation and learn from a very special teacher: the compiler. Start by writing your code in a supported language and learn how the compiler turns into IL.
Upvotes: 1