Update: um zu sehen, was tatsächlich passiert, ohne auf IL zurückgreifen zu müssen: Reflektor verwenden, um anonyme Methoden und erfasste Variablen zu verstehen
Wenn Sie verwenden:
public Bar CreateBar()
{
return new Bar(x, () => y);
}
Sie meinen damit implizit this.y
Der Delegierte ist also derjenige, der Referenz a Foo
die enthalten ist. Als solches ist die Instanz von Bar
(über den Delegierten) hält die gesamte Foo
lebendig (nicht müllsammelnd), bis die Bar
ist zur Abholung verfügbar.
Insbesondere ist es (in diesem Fall) nicht erforderlich, dass der Compiler eine zusätzliche Klasse für die Behandlung der erfassten Variablen erzeugt; das einzige, was erforderlich ist, ist die Foo
Instanz, so dass eine Methode erzeugt werden kann auf Foo
. Dies wäre noch komplizierter, wenn der Delegierte lokale Variablen (andere als this
).
In Bezug auf die Serialisierung ... gut, das erste, was ich sagen würde, ist, dass Serialisierung Delegaten eine sehr sehr schlechte Idee ist. Allerdings, BinaryFormatter
wird Delegierten gehen, und Sie können (theoretisch) mit einer serialisierten Bar
eine serialisierte Foo
und einen serialisierten Delegaten, um sie zu verknüpfen - aber nur wenn Sie markieren Foo
als [Serializable]
.
Aber ich betone - dies ist eine schlechte Idee . Ich verwende selten BinaryFormatter
(aus einer Vielzahl von Gründen), aber eine häufige Frage, die ich von Leuten sehe, die es benutzen, ist "warum versucht es, (irgendeinen beliebigen Typ) zu serialisieren". In der Regel lautet die Antwort: "Sie veröffentlichen ein Ereignis und versuchen, den Abonnenten zu serialisieren", wobei die häufigste Lösung darin besteht, das Feld des Ereignisses als [NonSerialized]
.
Anstatt IL zu betrachten; eine andere Möglichkeit, dies zu untersuchen, besteht darin, Reflektor im .NET 1.0-Modus zu verwenden (d. h. ohne anonyme Methoden einzubinden); dann können Sie sehen:
public Bar CreateBar()
{
return new Bar(this.x, new Func<int>(this.<CreateBar>b__0));
}
[CompilerGenerated]
private int <CreateBar>b__0()
{
return this.y;
}
Wie Sie sehen können, ging die Sache an Bar
ist ein Delegat für eine versteckte Methode (genannt <CreateBar>b__0()
) auf die aktuelle Instanz ( this
). Es ist also es die Instanz zum aktuellen Foo
die an den Bar
.