2015-10-11 43 views
5

爲什麼這個聲明+賦值導致錯誤:創建一個匿名函數關閉自身時,使用未分配的局部變量

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

雖然這並不:

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

在直觀的是,第一個陳述應該導致一個錯誤,但不能立即清楚爲什麼第二個陳述不是。

此外,我怎麼能告訴SystemEvents.SessionEnding事件實際上在handler(null, null)的調用後已取消訂閱? GetInvocationList只適用於代表。

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

第一個語句更相當於'SessionEndingEventHandler處理程序;',而在第二個語句中,您將它分配給null。它的未分配,直到lambda完全構建。請參閱http://stackoverflow.com/questions/1362204/how-to-remove-a-lambda-event-handler –

回答

9

這對於那些你期望這個失敗同樣的原因:當它的評估

int i = 1 - i; 

語句的右邊是分配前進行評估,並在時間,該變量尚未分配。

如果你想的lambda /代表改變的事情,考慮下面的語句:

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

因爲你創建i前拉姆達分配,這是可能i可以在任何值前使用已被分配給它。事實上,你不希望發生在你的情況下,不會改變編譯器的角度 - 你必須在變量被使用之前明確地賦值一個值。如果它是一個空值,那麼至少編譯器知道你正在考慮當它達到它時它會變爲空的可能性。

關於你最後的問題,SessionEndingEventHandler的一個委託。所以這將工作得很好:

var unsubscribed = SystemEvents.SessionEnding == null || 
    !SystemEvents.SessionEnding.GetInvocationList().Contains(handler); 
相關問題