2010-08-31 78 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表达式的另一个原因是,是否需要“适应”委托类型。即你确实想调用一个命名方法来处理这个事件,但是这个方法的签名不同于事件所要求的。在这种情况下,您希望将该方法重用于不同的事件或其他情况,其中事件的某些参数可能不适用。另一种情况可能是您希望引入新参数的位置,该参数是事件可能不提供的值(例如,所有具有您想要订阅的相同事件的对象集合的索引)。

有时可能会出现一个特殊情况,可以选择是自行使用命名方法还是使用匿名方法,然后调用该命名方法。值得注意的是,在没有其他实际理由的情况下,使用命名方法在这种特殊情况下会更有效,因为它从调用中删除了一个方法调用。在实践中,你可能永远都不会注意到这种差异,但它只是开销,所以如果没有具体的实际原因引发它,人们应该避免它,也就是直接订阅指定的方法。