Search code examples
c#.netbuildcompilationdebug-build

Why does debug build result in one more variable?


This is the code:

Employee e = new Employee() { Name = "Jeff", Age = 45 };

And this is how it is compiled when building a debug assembly:

Employee employee = new Employee();
employee.Name = "Jeff";
employee.Age = 45;
Employee employee2 = employee;

And that is how it's compiled when building a release:

Employee employee = new Employee();
employee.Name = "Jeff";
employee.Age = 45;

The question is: Why does debug build result in one more variable that references the same object?


Solution

  • SharpLab is taking the compiled IL and attempting to convert it back into readable C#, the resulting C# is not always an exact match either for the originally compiled code.

    If instead we look at the IL that was generated, in Debug mode we get the following (I've removed some nop (no-op) instructions to keep things tidy:

    .locals init (
        [0] class Employee
    )
    
    IL_0001: newobj instance void Employee::.ctor()
    IL_0006: dup
    IL_0007: ldstr "Jeff"
    IL_000c: callvirt instance void Employee::set_Name(string)
    IL_0012: dup
    IL_0013: ldc.i4.s 45
    IL_0015: callvirt instance void Employee::set_Age(int32)
    IL_001b: stloc.0
    IL_001c: ret
    

    In release, it's almost identical:

    IL_0000: newobj instance void Employee::.ctor()
    IL_0005: dup
    IL_0006: ldstr "Jeff"
    IL_000b: callvirt instance void Employee::set_Name(string)
    IL_0010: dup
    IL_0011: ldc.i4.s 45
    IL_0013: callvirt instance void Employee::set_Age(int32)
    IL_0018: pop
    IL_0019: ret
    

    The only real difference is that where the Debug version allocates a local variable for employee, the Release version does not since it's never used, and so isn't required.

    As we can see the "extra" variable you see in the Debug version doesn't really exist, it's just an artifact of SharpLab's attempt to convert the compiled IL back into readable C#, and in fact the Release version has "lost" a local variable because it wasn't required.