2012-06-21 17 views
9

Este código C# innecesaria:¿Por qué el compilador Añadir un local variable

private void LoadAssignments(AssignmentType assignmentType, Collection<Assignment> assignments) 
    { 
     bool flag; 
     DataTable lessons = this.GetResults(assignmentType); 
     try 
     { 
      IEnumerator enumerator = lessons.Rows.GetEnumerator(); 
      try 
      { 
       while (true) 
       { 
        flag = enumerator.MoveNext(); 
        if (!flag) 
        { 
         break; 
        } 
        DataRow row = (DataRow)enumerator.Current; 
       } 
      } 
      finally 
      { 
       IDisposable disposable = enumerator as IDisposable; 
       flag = disposable == null; 
       if (!flag) 
       { 
        disposable.Dispose(); 
       } 
      } 
     } 
     finally 
     { 
      flag = lessons == null; 
      if (!flag) 
      { 
       lessons.Dispose(); 
      } 
     } 
    } 

produce este CIL (.NET 4)

.method private hidebysig 
    instance void LoadAssignments (
     valuetype TTReporterCore.AssignmentType assignmentType, 
     class [mscorlib]System.Collections.ObjectModel.Collection`1<valuetype TTReporterCore.Assignment> assignments 
    ) cil managed 
{ 
    .locals init (
     [0] bool flag, 
     [1] class [System.Data]System.Data.DataTable lessons, 
     [2] class [mscorlib]System.Collections.IEnumerator enumerator, 
     [3] class [System.Data]System.Data.DataRow row, 
     [4] class [mscorlib]System.IDisposable disposable, 
     [5] bool flag1 
    ) 

    IL_0000: nop 
    IL_0001: ldarg.0 
    IL_0002: ldarg.1 
    IL_0003: call instance class [System.Data]System.Data.DataTable TTReporterCore.TTReader::GetResults(valuetype TTReporterCore.AssignmentType) 
    IL_0008: stloc.1 
    .try 
    { 
     IL_0009: nop 
     IL_000a: ldloc.1 
     IL_000b: callvirt instance class [System.Data]System.Data.DataRowCollection [System.Data]System.Data.DataTable::get_Rows() 
     IL_0010: callvirt instance class [mscorlib]System.Collections.IEnumerator [System.Data]System.Data.InternalDataCollectionBase::GetEnumerator() 
     IL_0015: stloc.2 
     .try 
     { 
      IL_0016: nop 
      IL_0017: br.s IL_0038 
      .loop 
      { 
       IL_0019: nop 
       IL_001a: ldloc.2 
       IL_001b: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() 
       IL_0020: stloc.0 
       IL_0021: ldloc.0 
       IL_0022: stloc.s flag1 
       IL_0024: ldloc.s flag1 
       IL_0026: brtrue.s IL_002b 

       IL_0028: nop 
       IL_0029: br.s IL_003d 

       IL_002b: ldloc.2 
       IL_002c: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current() 
       IL_0031: castclass [System.Data]System.Data.DataRow 
       IL_0036: stloc.3 
       IL_0037: nop 

       IL_0038: ldc.i4.1 
       IL_0039: stloc.s flag1 
       IL_003b: br.s IL_0019 
      } 

      IL_003d: nop 
      IL_003e: leave.s IL_0062 
     } 
     finally 
     { 
      IL_0040: nop 
      IL_0041: ldloc.2 
      IL_0042: isinst [mscorlib]System.IDisposable 
      IL_0047: stloc.s disposable 
      IL_0049: ldloc.s disposable 
      IL_004b: ldnull 
      IL_004c: ceq 
      IL_004e: stloc.0 
      IL_004f: ldloc.0 
      IL_0050: stloc.s flag1 
      IL_0052: ldloc.s flag1 
      IL_0054: brtrue.s IL_0060 

      IL_0056: nop 
      IL_0057: ldloc.s disposable 
      IL_0059: callvirt instance void [mscorlib]System.IDisposable::Dispose() 
      IL_005e: nop 
      IL_005f: nop 

      IL_0060: nop 
      IL_0061: endfinally 
     } 

     IL_0062: nop 
     IL_0063: nop 
     IL_0064: leave.s IL_007e 
    } 
    finally 
    { 
     IL_0066: nop 
     IL_0067: ldloc.1 
     IL_0068: ldnull 
     IL_0069: ceq 
     IL_006b: stloc.0 
     IL_006c: ldloc.0 
     IL_006d: stloc.s flag1 
     IL_006f: ldloc.s flag1 
     IL_0071: brtrue.s IL_007c 

     IL_0073: nop 
     IL_0074: ldloc.1 
     IL_0075: callvirt instance void [System]System.ComponentModel.MarshalByValueComponent::Dispose() 
     IL_007a: nop 
     IL_007b: nop 

     IL_007c: nop 
     IL_007d: endfinally 
    } 

    IL_007e: nop 
    IL_007f: ret 
} 

¿Por qué el MSIL añadir el flag1, proseguir la ejecución del la misma lógica para establecer la bandera, establecer la bandera 1 para marcar y finalmente, verificar para! bandera1. Esto me parece una ineficiencia del compilador.

ACTUALIZACIÓN: Yo estaba usando JustDecompile de Telerik y aunque los resultados son bastante diferentes de ILDASM, el booleano adicional todavía se crea en modo de depuración.

Además, modifiqué el código eliminando completamente el booleano y la versión de depuración aún agrega un booleano. Realmente estoy buscando por qué el compilador hace esto.

+3

¿Qué ocurre si compila en modo Release en lugar de Debug? –

+0

Mismo resultado en modo de lanzamiento. – kakridge

+0

El nombre de la variable real se asemeja a "CS $ 4 $ 0000", no a "flag1". Y * * se optimiza en la compilación de lanzamiento. No estoy seguro de qué desensamblador está utilizando, pero suena borken. Use ildasm.exe para ver esto. –

Respuesta

2

Parece que se creó un local temporal para contener los resultados de la comparación (es decir, desechable == nulo).

Tratando este ejemplo:

class Program 
{ 
    static void Main() 
    { 
     if (1 == 1) return; 
    } 
} 

..es que producen la siguiente IL en mi caja (Microsoft (R) Visual C# 2010 Compilador versión 4.0.30319.1):

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    .maxstack 1 
    .locals init (bool V_0) 
    IL_0000: nop 
    IL_0001: ldc.i4.0 
    IL_0002: stloc.0 
    IL_0003: br.s  IL_0005 
    IL_0005: ret 
} 

V_0 local es creado, aunque en realidad no se use. Creo que es una optimización obvia incluso para la compilación "no optimizada :) ... o más probable: todo el código necesario se genera para habilitar la depuración. No sé cómo podría usarse en una sesión de depuración, pero es mi mejor suposición.

Cuando se compiló optimizado (es decir, configuración de versión) no veo el local adicional.

0

Cuando escribí un programa similar, la variable adicional no apareció en el modo de lanzamiento. Lo mismo en vista de conjunto, la depuración mostró el extra de ser conjunto variable ([ebp-44h]) y la liberación no:

Depuración:

enter image description here

de salida:

enter image description here

+4

Parece que se saltó la primera palabra del título. –

Cuestiones relacionadas