2010-07-15 54 views
8

除了多次使用它會違反DRY原理的事實之外,您能否看到這一行的缺點?這看起來很簡單,但是我沒有看到別人提出這個事實,這讓我懷疑它是否有缺點。One Liner:WeakReference-to-a-Lambda Event Handler

這段代碼創建一個WeakReference給一個方法,然後註冊一個調用引用的目標的事件處理函數。

SomeEvent += (sender, e) => ((Action)(new WeakReference((Action)ProcessEvent)).Target)(); 

感謝,

+0

您是否看到我的問題/答案[here](http://stackoverflow.com/questions/1747235/weak-event-handler-model-for-use-with-lambdas)?這不是一句話,但我*認爲*它的工作原理... – Benjol 2011-09-22 09:57:33

回答

11

我不認爲這種模式符合你的期望。你是否試圖阻止事件持有對當前對象的引用,以防止內存泄漏? lambda表達式將捕獲this的值以便評估ProcessEvent(假設ProcessEvent是一個實例方法),所以您仍然有泄漏。此代碼與SomeEvent += (sender, e) => ProcessEvent();相同。

你可能會試圖做一些更多這樣的(這也不是你想要的):

var reference = new WeakReference((Action)ProcessEvent); 
SomeEvent += (sender, e) => ((Action)reference.Target)(); 

現在lambda表達式將捕獲的WeakReference,所以你不會有很強的借鑑意義到this。不幸的是,沒有別的東西引用從ProcessEvent創建的委託,所以即使this仍然存在,它也會在下一個GC中刪除。 (這也不檢查目標爲空)。

你可以嘗試這樣的事:

public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove) 
{ 
    var reference = new WeakReference(action.Target); 
    var method = action.Method; 
    EventHandler handler = null; 
    handler = delegate(object sender, EventArgs e) 
    { 
     var target = reference.Target; 
     if (target != null) 
     { 
      method.Invoke(target, null); 
     } 
     else 
     { 
      remove(handler); 
     } 
    }; 
    return handler; 
} 

,然後用它是這樣的:

SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h); 

這將保持一個弱引用的processEvent的接收器,並會自動刪除事件事件處理程序在收集完成之後,只要定期提升事件就應該防止內存泄漏。

+0

這不適用於任何事件。您必須專門針對您所需的* exact *事件,例如,用PropertyChangedEventArgs和EventHandler替換帶有PropertyChangedEventHandler的EventArgs。 我試圖建立一個通用的版本,你可以傳入類型但看起來不起作用。 – 2012-07-06 16:07:13

0

它不是很有可讀性。如果您必須通過逐步調試來進行調試,那麼這些操作中的任何一個都可能會失敗,但是該單行將會失敗。而且,你只能得到堆棧跟蹤中引用的那一行。

您通常希望避免爲了可維護性而在一行中做太多事情。

相關問題