2015-10-11 11 views
5

Warum diese Erklärung + Zuordnung einen Fehler verursachen:Verwendung von nicht zugewiesenen lokalen Variablen, wenn eine anonyme Funktion auf sich selbst schließt die Schaffung

// Use of unassigned local variable 'handler'. 
SessionEndingEventHandler handler = (sender, e) => { isShuttingDown = true; SystemEvents.SessionEnding -= handler; }; 

während dies nicht:

SessionEndingEventHandler handler = null; 
handler = (sender, e) => { isShuttingDown = true; SystemEvents.SessionEnding -= handler; }; 

In ist intuitiv, dass die erste Anweisung sollte einen Fehler verursachen, aber nicht sofort klar, warum die zweite nicht ist.

Außerdem, wie könnte ich sagen, ob das SystemEvents.SessionEnding Ereignis wurde tatsächlich nach dem Aufruf an handler(null, null) abgemeldet? Die GetInvocationList funktioniert nur mit Delegaten.

SystemEvents.SessionEnding += handler; 
handler(null, null); 
+1

Die erste Anweisung entspricht mehr dem 'SessionEndingEventHandler-Handler;', während sie in der zweiten Anweisung null zugewiesen wird. Es ist nicht zugewiesen, bis das Lambda vollständig aufgebaut ist. Siehe http://stackoverflow.com/questions/1362204/how-to-remove-a-lambda-event-handler –

Antwort

9

Es ist aus dem gleichen Grunde, dass Sie dies nicht erwarten würden:

int i = 1 - i; 

Die rechte Seite der Aussage vor der Zuweisung ausgewertet wird, und zu der Zeit, wenn es bewertet ist, Die Variable wurde noch nicht vergeben.

Im Fall denken Sie lambda/Delegierten Dinge zu ändern, sollten Sie die folgende Anweisung:

int i = ((Action)() => 1 - i)(); 

Da Sie das Lambda sind zu schaffen, bevor i zugeordnet ist, ist es möglich dass i vor jedem Wert verwendet werden könnte, wurde ihm zugewiesen. Die Tatsache, dass dies in Ihrem Fall nicht erwartet wird, ändert nichts an der Perspektive des Compilers - Sie müssen der Variablen explizit einen Wert zuweisen, bevor sie verwendet wird. Wenn es ein Null-Wert ist, dann weiß zumindest der Compiler, dass Sie die Möglichkeit in Betracht ziehen, dass es Null wird, wenn Sie dazu kommen.

In Bezug auf Ihre letzte Frage ist ein SessionEndingEventHandler ein Delegierter. Das würde also gut funktionieren:

Verwandte Themen