2011-05-16 15 views
7

tengo este código,Código Generar Clase MSIL llamado <> c__DisplayClass1

private bool MatchingBreak(IEnumerable<CarriagewaySummary> breaks, int startMetres, int divisionPosition) 
    { 
     CarriagewaySummary matchingBreak = breaks.Where(x => 
     { 
      return x.StartMetres == startMetres && x.EndMetres == divisionPosition; 
     }).SingleOrDefault(); 
     return matchingBreak != null; 
    } 

¿Por qué eso generar una clase anidada llamada <> c__DisplayClass1 en el MSIL?

.class nested private auto ansi sealed beforefieldinit <>c__DisplayClass1 
extends object 
{ 
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
    01 00 00 00 
) 
// Fields 
.field public int32 startMetres 
.field public int32 divisionPosition 

// Methods 
.method public hidebysig specialname rtspecialname 
    instance void .ctor() cil managed 
{ 
    // Method begins at RVA 0x56fb 
    // Code size 7 (0x7) 
    .maxstack 8 

    IL_0000: ldarg.0 
    IL_0001: call instance void object::.ctor() 
    IL_0006: ret 
} // End of method <>c__DisplayClass1..ctor 

.method public hidebysig 
    instance bool <MatchingBreak>b__0 (
     class TreatmentLengthDynamicSegmentation.Domain.CarriagewaySummary x 
    ) cil managed 
{ 
    // Method begins at RVA 0x5704 
    // Code size 37 (0x25) 
    .maxstack 2 
    .locals init (
     [0] bool 
    ) 

    IL_0000: nop 
    IL_0001: ldarg.1 
    IL_0002: callvirt instance int32 TreatmentLengthDynamicSegmentation.Domain.CarriagewaySummary::get_StartMetres() 
    IL_0007: ldarg.0 
    IL_0008: ldfld int32 class TreatmentLengthDynamicSegmentation.ScriptHelpers.DivisionManager/<>c__DisplayClass1::startMetres 
    IL_000d: bne.un.s IL_001f 
    IL_000f: ldarg.1 
    IL_0010: callvirt instance int32 TreatmentLengthDynamicSegmentation.Domain.CarriagewaySummary::get_EndMetres() 
    IL_0015: ldarg.0 
    IL_0016: ldfld int32 class TreatmentLengthDynamicSegmentation.ScriptHelpers.DivisionManager/<>c__DisplayClass1::divisionPosition 
    IL_001b: ceq 
    IL_001d: br.s IL_0020 
    IL_001f: ldc.i4.0 
    IL_0020: stloc.0 
    IL_0021: br.s IL_0023 
    IL_0023: ldloc.0 
    IL_0024: ret 
} // End of method <>c__DisplayClass1.<MatchingBreak>b__0 

} // End of class TreatmentLengthDynamicSegmentation.ScriptHelpers.DivisionManager/<>c__DisplayClass1 

El código generado está interfiriendo con el análisis de código Nitriq, por lo que quiere entender por qué está ahí.

+0

Me pregunto, ¿por qué elegiste usar la sintaxis de bloque lambda? ¿Por qué no 'breaks.Where (x => x.StartMetres == startMetres && x.EndMetres == divisionPosition) .SingleOrDefault();'? – Dykam

Respuesta

9

Si utiliza variables locales en una lambda, debe estar en el montón. El lambda podría usarse después de que la función que lo creó salga. Las variables locales normales (que viven en la pila/registros) dejan de ser válidas cuando la función finaliza, por lo que no se pueden usar aquí.

Así que el compilador de C# crea una clase para mantener las variables locales capturadas. Esa es la que estás viendo.

Tenga en cuenta que C# captura la variable real, no su valor actual. Así que conceptualmente se captura por referencia. La semántica de captura significa que el compilador necesita crear un objeto contenedor por alcance.

http://csharpindepth.com/Articles/Chapter5/Closures.aspx


En su código

x => 
    { 
     return x.StartMetres == startMetres && x.EndMetres == divisionPosition; 
    } 

La lambda utiliza startMetres y divisionPosition, por lo que ambos son capturados y se ponen en esa clase anidada.

6

Está utilizando una lambda para el método de extensión Where, que requiere que el compilador genere una clase siempre que la lambda capture variables externas. En este caso, se capturan los parámetros startMetres y divisionPosition.

Está viendo la clase que genera el compilador para contener las variables capturadas.

+0

¿Lo hace para cualquier método de extensión? ¿Alguna razón en particular por la que hace eso? – peter

+1

No es el método de extensión, es el lambda. Necesita una clase para mantener el método anónimo que has pasado. – dlev

+0

Tiene sentido. Gracias. – peter

Cuestiones relacionadas