方法订阅与 lambda 委托订阅 - 哪个以及为什么?

发布于 2024-09-17 09:52:11 字数 213 浏览 5 评论 0原文

我看到有些人倾向于将方法传递给回调/事件,然后有时只传递 lambda。

有人能谈谈两者之间的区别吗?我原本以为它们是相同的,但我所看到的实现的不一致有时让我想知道是否存在一种情况比另一种更可取?显然,如果有大量的代码,它不应该是现场 lambda,但除此之外......

你们都可以概述两者之间的任何差异(如果有的话),并概述当两者都存在时在两者之间进行选择时使用的规则有空吗?

I have seen some people leaning on handing methods to callbacks/events and then sometimes just handing them lambdas.

Can anybody speak to any difference between the two? I would have originally thought them to be the same, but the inconsistency I have seen implemented sometimes makes me wonder if there is a case where one is preferable over the other? Obviously if there is a very large ammount of code it shouldn't be an on the spot lambda, but otherwise..

Can you all outline any differences between the two if any, and outline the rules you use in choosing between the two when both are available?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

[浮城] 2024-09-24 09:52:12

两者之间最大的区别之一是您可以轻松地取消订阅活动。使用基于方法的方法取消订阅是一个简单的操作,只需使用原始方法

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 表达式的便利性。

One of the biggest differences between the two is the ease by which you can unsubscribe from the event. With the method based approach unsubscribing is a simple operation, simply use the original method

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

With lambdas this is not as simple. You must store away the lambda expression and to be used later on to unsbuscribe from the event

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;

It really detracts from the convenience of using lambda expressions.

财迷小姐 2024-09-24 09:52:12

在大多数具有 lambda 的语言(包括 C#)中,在方法内创建 lambda 会创建一个闭包——也就是说,声明方法内的局部变量将对 lambda 可见。这是我所知道的最大的区别。

除此之外,除非您以某种方式以可在另一个函数中访问的方式命名事件处理程序,否则您会发现稍后很难分离事件处理程序。这可以通过将委托存储在实例级或类级变量中来实现,但它可能有点难看。

In most languages that have lambdas (including C#), creating a lambda inside a method creates a closure -- that is, the local variables inside the declaring method will be visible to the lambda. That's the biggest difference i'm aware of.

Aside from that, unless you name your event handler somehow, in a way that's accessible in another function, you'll find it hard to detach the event handler later. This is doable by storing the delegate in an instance- or class-level variable, but it can be kinda ugly.

卷耳 2024-09-24 09:52:12

使用 Lambda 的最大原因是延迟执行,即您定义了要执行的操作,但要稍后才能获得参数。通常,您不会将 lambda 表达式用于事件和回调;您使用匿名方法。

对于不需要取消订阅的简单事件,使用事件和回调的匿名方法是可以的。对我来说最大的决定因素是我在哪里声明它。我不会将表单的事件处理程序声明为匿名方法,但如果我有一个短暂的需要连接到事件,那么可能没问题。

一般来说,我对回调和事件使用实际方法多于匿名方法;我正在处理的事件与对象的生命周期相关,而不是与方法的生命周期相关,并且我发现在连接它们的函数外部明确定义回调在代码中更清晰。其中一些是个人喜好。

The biggest reason for using a Lambda is to have delayed execution, i.e. you define the operations you want to perform, but you won't have the parameters until later. You generally don't use lambdas for events and callbacks; you use anonymous methods.

Using anonymous methods for events and callbacks is okay for simple events that you don't need to unsubscribe to. The biggest determining factor for me is where I'm declaring it. I'm not going to declare an event handler for a form as an anonymous method, but if I have a short-lived need to connect to an event, it might be okay.

In general, I use actual methods for callbacks and events more than anonymous methods; the events I'm handling are tied to the lifetime of the object, not the lifetime of the method, and I find that it's clearer in code to have callbacks clearly defined external to the function that hooks them up. Some of that is personal preference.

王权女流氓 2024-09-24 09:52:12

在大多数情况下,实际差异很小。使用哪一个主要取决于个人喜好(即您希望代码看起来像什么)。在某些情况下,有一些实际原因选择其中一种:

  1. 接受的答案中所述,取消订阅匿名方法是比取消订阅命名方法更复杂。如果没有名称,则无法引用匿名方法,除非通过在运行时创建的声明匿名方法的委托实例来引用。使用命名方法,可以取消订阅委托,而无需保留对原始委托(或其等效项)的引用。
  2. 另一方面,首选 lambda 表达式的原因是事件处理程序是声明 lambda/匿名方法的命名方法所特有的实现细节。这有助于保持此类实现细节的私有性,并且对于使用它们的方法来说是本地的。
  3. 使用 lambda 表达式的另一个原因是是否需要“调整”委托类型。即,您确实想要调用命名方法来处理事件,但该方法具有与事件所需的签名不同的签名。在这种情况下,您可能希望针对不同的事件或其他情况重用该方法,其中事件中的某些参数可能不适用。另一种情况可能是您想要引入一个新参数,该参数的值可能是事件无法提供的(例如,所有具有您想要订阅的相同事件的对象集合的索引)。

有时可能会出现一种特殊情况,即选择是单独使用命名方法,还是使用然后调用该命名方法的匿名方法。需要注意的是,在没有选择其中一种的其他实际原因的情况下,在这种特殊情况下使用命名方法的效率稍高,因为它从调用中删除了一个方法调用。在实践中,您可能永远不会注意到这种差异,但这只是开销,因此如果没有具体的、实际的原因来引发它,人们可能应该避免它,即直接订阅命名方法。

In most cases, there is little practical difference. Which one to use is mainly a matter of personal preference (i.e. what you want the code to look like). In some cases, there are some practical reasons to prefer one over the other:

  1. As noted in the accepted answer, unsubscribing an anonymous method is more complex than unsubscribing a named method. Without a name, there's no way to refer to the anonymous method except by the delegate instance created at runtime where the anonymous method is declared. Using a named method, the delegate can be unsubscribed without having retained a reference to the original delegate (or its equivalent).
  2. On the other hand, a reason to prefer a lambda expression is when the handler for the event is an implementation detail unique to the named method in which the lambda/anonymous method is declared. This can help keep such implementation details private and local to the method where they are used.
  3. Another reason one might use a lambda expression is if there's a need to "adapt" the delegate type. I.e. you do want to call a named method to handle the event, but that method has a different signature than that required by the event. This might be the case where you want to reuse the method for different events or other situations, where some of the parameters from the event might not be applicable. Another case might be where you want to introduce a new parameter a value for which the event might not provide (e.g. an index for a collection of objects all having the same event you want to subscribe to).

There is one special case that may sometimes come up, which is the choice of whether to use a named method by itself, or to use an anonymous method that then calls that named method. It is important to note that, in absence of other practical reasons for choosing one over the other, using a named method is marginally more efficient in this particular case, because it removes one method call from the invocation. In practice, you'll probably never notice the difference, but it's just overhead so if there's no specific, practical reason to incur it, one should probably avoid it, i.e. subscribe the named method directly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文