aaronburro
aaronburro

Reputation: 554

Emitted IL NullReferenceException on call to method on Int32

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

Answers (1)

Yennefer
Yennefer

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

Related Questions