2010-08-31 79 views
5

我見過一些人靠處理方法來回調/事件,然後有時只是把它們遞給lambda表達式。方法訂閱vs lambda委託訂閱 - 哪一個?爲什麼?

有人能說兩者有什麼不同嗎?我本來以爲他們是一樣的,但是我所看到的不一致有時候讓我懷疑是否有一種情況比另一種更可取?很顯然,如果代碼量非常大,它不應該是一個現場lambda,否則..

你們可以概述兩者之間的任何差異(如果有的話),並概述了您在選擇兩者都可用時呢?

回答

7

之一兩者之間最大的區別是,通過它可以從事件退訂的難易程度。使用基於方法的退訂方法是一種簡單的操作,只需使用原始方法

m_button.Click += OnButtonClick; 
... 
m_button.Click -= OnButtonClick; 

隨着lambdas這不是那麼簡單。您必須儲存起來的lambda表達式,並在以後使用從事件

m_button.Click += delegate { Console.Write("here"); } 
... 
// Fail 
m_button.Click -= delegate { Console.Write("here"); } 

EventHandler del = delegate { Console.Write("here"); } 
m_button.Click += del; 
... 
m_button.Click -= del; 

這真的使用lambda表達式的便利有損於unsbuscribe。

+0

我已經習慣了+ =(sender,e)=> {}並從未考慮過它,但如果我想要,我無法刪除那個特定的聽衆,好點.. – 2010-08-31 15:11:14

+0

@Jimmy,通常時間你不需要,這一點變得無關緊要。但是這對你所處的時代來說很煩人。 – JaredPar 2010-08-31 15:13:09

2

在有lambda表達式(包括C#)大多數語言中,創建一個方法內拉姆達創建一個封閉 - 也就是說,申報方法內的局部變量將是拉姆達可見。這是我意識到的最大差異。

除此之外,除非你以某種方式命名您的事件處理程序,在某種程度上這是另一個函數訪問,你會發現它很難以後分離的事件處理程序。這可以通過將委託存儲在實例或類級別的變量中來實現,但它可能有點醜陋。

1

的使用Lambda最大的原因是已經延遲執行,即你定義要執行的操作,但你不會有參數,直到後來。您通常不使用lambda表示事件和回調;你使用匿名方法。

使用事件和回調匿名方法是沒關係的,你不需要退訂簡單事件。對我而言,最重要的決定因素就是我宣佈它的地方。我不打算聲明一個窗體的事件處理程序作爲匿名方法,但是如果我有一個短暫的需要連接到一個事件,它可能沒問題。

一般情況下,我使用的回調和比匿名方法更實際事件的方法;我處理的事件與該對象的生命週期相關,而不是該方法的生命週期,並且我發現它在代碼中更清晰,以便將回調明確定義在將它們掛鉤的函數外部。其中一些是個人偏好。

+1

Lambdas不會在正常意義上被延遲執行。他們只是代表,並具有正常的委託行爲。延遲執行通常用於描述與lambda表達式不同的語義的LINQ查詢。 – JaredPar 2010-08-31 16:25:53

+0

你說得對,好點。 LINQ是我主要使用Lambdas的地方,這個區別在我腦海中變得模糊 – 2010-08-31 16:44:42

0

在大多數情況下,幾乎沒有實際區別。哪一個使用主要是個人喜好的問題(即你想要的代碼看起來像一樣)。在某些情況下,也有一些現實的原因更喜歡一個比其他:

  1. 正如the accepted answer指出,退訂匿名方法比退訂的命名的方法更加複雜。如果沒有名稱,除了聲明匿名方法的運行時創建的委託實例外,沒有辦法引用匿名方法。使用命名方法,委託人可以在沒有保留對原始委託人(或其等價物)的引用的情況下取消訂閱。
  2. 另一方面,偏好lambda表達式的原因是,事件的處理程序是聲明lambda /匿名方法的命名方法唯一的實現細節。這可以幫助保持這些實現細節私有和局部使用它們的方法。
  3. 可以使用lambda表達式的另一個原因是,是否需要「適應」委託類型。即你確實想調用一個命名方法來處理這個事件,但是這個方法的簽名不同於事件所要求的。在這種情況下,您希望將該方法重用於不同的事件或其他情況,其中事件的某些參數可能不適用。另一種情況可能是您希望引入新參數的位置,該參數是事件可能不提供的值(例如,所有具有您想要訂閱的相同事件的對象集合的索引)。

有時可能會出現一個特殊情況,可以選擇是自行使用命名方法還是使用匿名方法,然後調用該命名方法。值得注意的是,在沒有其他實際理由的情況下,使用命名方法在這種特殊情況下會更有效,因爲它從調用中刪除了一個方法調用。在實踐中,你可能永遠都不會注意到這種差異,但它只是開銷,所以如果沒有具體的實際原因引發它,人們應該避免它,也就是直接訂閱指定的方法。