Was löst abschließend eine neue Instanz der erfassten Variablen aus?

Ich lese Jon SkeetsC # im Detail.

Auf Seite 175 finden Sie ein Beispiel in Listing 5.13, „Erfassen mehrerer Variableninstanzen mit mehreren Delegaten“.

List<ThreadStart> list = new List<ThreadStart>();

for(int index=0; index < 5; index++;)
{
    int counter = index*10;
    list.Add(delegate
          {
              Console.WriteLine(counter);
              counter++;
          }
        );
}

foreach(ThreadStart t in list)
{
    t();
}

list[0]();
list[0]();
list[0]();

list[1]();

In der Erklärung nach dieser Auflistung sagt er, dass "in diesem Fall jede der Stellvertreterinstanzen eine andere Variable erfasst hat".

Ich verstehe das gut genug, weil ich verstehe, dass der Compiler jedes Mal, wenn Sie eine Variable schließen, eine AWL generiert, die sie in eine neue Klasse einkapselt, die speziell dafür erstellt wurde, dass diese Variable erfasst werden kann (im Wesentlichen wird sie zu einem Referenztyp, sodass der Wert, auf den sie verweist to wird mit dem Stack-Frame des aktuell ausgeführten Scopes nicht zerstört).

Aber dann spricht er darüber, was passiert wäre, wenn wir gefangen genommen hättenindex direkt anstatt die zu erstellencounter Variable - "Alle Delegierten hätten dieselbe Variable geteilt".

Das verstehe ich nicht. Nichtindex im gleichen Umfang wiecounter? Warum sollte der Compiler nicht auch eine neue Instanz von erstellen?index für jeden Teilnehmer?

Hinweis: Ich denke, ich habe es herausgefunden, als ich diese Frage getippt habe, aber ich werde die Frage hier für die Nachwelt belassen. Ich denke, die Antwort ist dasindex ist eigentlich in einem anderen umfang alscounter. Index wird im Wesentlichen als "außerhalb" der for-Schleife deklariert ... es ist jedes Mal dieselbe Variable.

Schauen Sie sich die IL an, die für a generiert wurdefor Schleife, es beweist, dass die Variablen außerhalb der Schleife deklariert sind (length undi wurden Variablen in der deklariertfor Schleifendeklaration).

.locals init (
    [0] int32 length,
    [1] int32 i,
    [2] bool CSIch verstehe das gut genug, weil ich verstehe, dass der Compiler jedes Mal, wenn Sie eine Variable schließen, eine AWL generiert, die sie in eine neue Klasse einkapselt, die speziell dafür erstellt wurde, dass diese Variable erfasst werden kann (im Wesentlichen wird sie zu einem Referenztyp, sodass der Wert, auf den sie verweist to wird mit dem Stack-Frame des aktuell ausgeführten Scopes nicht zerstört).0000
)

IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: stloc.1
IL_0006: br.s IL_001b
// loop start (head: IL_001b)
    IL_0008: nop
    IL_0009: ldloca.s i
    IL_000b: call instance string [mscorlib]System.Int32::ToString()
    IL_0010: call void [mscorlib]System.Console::WriteLine(string)
    IL_0015: nop
    IL_0016: nop
    IL_0017: ldloc.1
    IL_0018: ldc.i4.1
    IL_0019: add
    IL_001a: stloc.1

    IL_001b: ldloc.1
    IL_001c: ldloc.0
    IL_001d: clt
    IL_001f: stloc.2
    IL_0020: ldloc.2
    IL_0021: brtrue.s IL_0008
// end loop

Eine Sache, die ich denke, dass das Buch in Bezug auf dieses Thema besser gemacht haben könnte, ist wirklich zu erklären, was der Compiler tut, denn all diese "Magie" ist sinnvoll, wenn Sie verstehen, dass der Compiler die über-geschlossene Variable in eine neue Klasse einhüllt.

Bitte korrigieren Sie eventuelle Missverständnisse. Fühlen Sie sich auch frei, näher darauf einzugehen und / oder meine Erklärung zu ergänzen.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage