tags:

views:

54

answers:

1

I have a class which has a private variable of type generic Stack.
Inside the class I've declared a Foo method.
After examining the IL I've noticed that the target of the method Push is actually the method call set_Property2 rather then the field of the class.
How does the compiler actually make the connection between the two?


public class A
{
    public int Property1 { get; set; }
    public int Property2 { get; set; }
}

public class ShortDemo
{
    private Stack<A> _stack = new Stack<A>();

    private void Foo()
    {
        _stack.Push(new A()
        {
            Property1 = 1,
            Property2 = 2
        });
    }
}

And the IL:


.method private hidebysig instance void Foo() cil managed
{
    .maxstack 3
    .locals init (
        [0] class ConsoleApplication1.A g__initLocal0)
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldfld class [System]System.Collections.Generic.Stack1 ConsoleApplication1.ShortDemo::_stack
    L_0007: newobj instance void ConsoleApplication1.A::.ctor()
    L_000c: stloc.0 
    L_000d: ldloc.0 
    L_000e: ldc.i4.1 
    L_000f: callvirt instance void ConsoleApplication1.A::set_Property1(int32)
    L_0014: nop 
    L_0015: ldloc.0 
    L_0016: ldc.i4.2 
    L_0017: callvirt instance void ConsoleApplication1.A::set_Property2(int32)
    L_001c: nop 
    L_001d: ldloc.0 
    L_001e: callvirt instance void [System]System.Collections.Generic.Stack1::Push(!0)
    L_0023: nop 
    L_0024: ret 
}

When I change the Foo method to work without object initialzers then it becomes reasonable and the ldfld line is at the top of the stack. to my first:


 private void Foo()
{   
    A instance = new A()
                 {
                     Property1 = 1,
                     Property2 = 2
                 };

   _stack.Push(instance);
}

.method private hidebysig instance void Foo() cil managed
{
    .maxstack 2
    .locals init (
        [0] class ConsoleApplication1.A instance,
        [1] class ConsoleApplication1.A g__initLocal0)
    L_0000: nop 
    L_0001: newobj instance void ConsoleApplication1.A::.ctor()
    L_0006: stloc.1 
    L_0007: ldloc.1 
    L_0008: ldc.i4.1 
    L_0009: callvirt instance void ConsoleApplication1.A::set_Property1(int32)
    L_000e: nop 
    L_000f: ldloc.1 
    L_0010: ldc.i4.2 
    L_0011: callvirt instance void ConsoleApplication1.A::set_Property2(int32)
    L_0016: nop 
    L_0017: ldloc.1 
    L_0018: stloc.0 
    L_0019: ldarg.0 
    L_001a: ldfld class [System]System.Collections.Generic.Stack`1 ConsoleApplication1.ShortDemo::_stack
    L_001f: ldloc.0 
    L_0020: callvirt instance void [System]System.Collections.Generic.Stack`1::Push(!0)
    L_0025: nop 
    L_0026: ret 
}