Aktion / Lambda Ausdruck Speicherverwaltung Frage

8

Ich speichere eine Aktion in einer lokalen Variablen, dann benutze ich danach, dass die lokale Variable außerhalb des Bereichs liegt. Besteht die Gefahr, dass ich gereinigt werde, bevor ich es benutze? Hier ist ein Beispiel:

%Vor%

Sie können also in diesem Beispiel sehen, dass die Funktion eine Liste von Aktionen zurückgibt, die baseMap aufrufen. baseMap ist nur eine lokale Variable. Ist die Tatsache, dass es innerhalb der anderen Aktionen aufgerufen wird genug für .NET, um es nicht zu bereinigen?

    
dontangg 01.06.2011, 14:40
quelle

4 Antworten

11

Ich beziehe mich auf Abschnitt 5.1.7 der C # 4-Spezifikation, die besagt:

  

Wenn die lokale Variable von einer anonymen Funktion erfasst wird, erstreckt sich ihre Lebensdauer mindestens so lange, bis die von der anonymen Funktion erstellte Delegat- oder Ausdrucksstruktur zusammen mit anderen Objekten, die die aufgezeichnete Variable referenzieren, für die Garbage Collection geeignet ist.

Auch wenn die Kontrolle das Ende des Bereichs des lokalen Bereichs überschreitet, wird die Lebensdauer des lokalen Bereichs erweitert. In der Praxis machen wir das, indem wir das local in ein Feld einer closure-Klasse verwandeln und dann die Klasse am Leben erhalten, indem wir sie im Delegate (oder im Ausdrucksbaum) referenzieren.

Beachten Sie jedoch, dass Sie auf das gegenteilige Problem stoßen können; Manchmal leben die Dinge länger als du willst:

%Vor%

Wie dies heute in C # funktioniert, ist die Schließung, die für die zwei Delegierten generiert wird, die sowohl "billig" als auch "teuer" am Leben erhält, solange der Delegierte mit längerer Lebensdauer nicht wirklich lebt Verwenden Sie "teuer"! (VB, JScript und viele andere Sprachen, die Schließungen haben, haben dieses Problem ebenfalls.)

Was wir hier tun könnten, ist, diese Situation im Compiler zu erkennen und zwei Closures zu erzeugen. Wir überlegen, dies für eine zukünftige Version von C # zu tun.

    
Eric Lippert 01.06.2011, 15:31
quelle
5

Nein, es ist nicht in Gefahr. Eine anonyme Methode, die eine lokale Variable außerhalb dieser anonymen Methode verwendet, wird in eine neue Klasse mit einem Feld kompiliert, das diese lokale Variable und eine Methode speichert, die der anonymen Methode entspricht.

In Ihrem Fall wird dies etwa wie folgt aussehen:

%Vor%

Die Initialisierung der Liste sieht dann ungefähr so ​​aus:

%Vor%

BTW: Ihre Syntax ist ein bisschen aus. Die Listenerstellung wird nicht kompiliert. Es sollte so aussehen:

%Vor%     
Daniel Hilgarth 01.06.2011 14:43
quelle
1

Es liegt nicht außerhalb des Gültigkeitsbereichs, da es von Ihrer Liste referenziert wird. Daher wird es nicht vom Garbage Collector bereinigt.

Also nein, du bist nicht in Gefahr

    
thekip 01.06.2011 14:46
quelle
0

Der Delegat ist ein Referenztyp und wird nicht bereinigt, bis es mindestens eine Referenz von root gibt. Wenn Sie also den Aktionsdelegaten erstellen und den Delegierten aus der Methode herausholen, machen Sie sich keine Sorgen über das Aufräumen.

    
TcKs 01.06.2011 14:45
quelle

Tags und Links