C# 中的 lambda 表达式?

发布于 2024-08-24 18:38:30 字数 311 浏览 5 评论 0原文

我对这些很陌生,有人可以解释一下(以下代码的)重要性,或者提供一些有关 lambda 表达式的有用信息的链接吗?我在测试中遇到以下代码,我想知道为什么有人会这样做:

foo.MyEvent += (o, e) => { fCount++; Console.WriteLine(fCount); };

foo.MyEvent -= (o, e) => { fCount++; Console.WriteLine(fCount); };

我的直觉告诉我这是简单的事情而不是错误,但我对这些表达式的了解不够,无法理解为什么要这样做。

I'm rather new to these could someone explain the significance (of the following code) or perhaps give a link to some useful information on lambda expressions? I encounter the following code in a test and I am wondering why someone would do this:

foo.MyEvent += (o, e) => { fCount++; Console.WriteLine(fCount); };

foo.MyEvent -= (o, e) => { fCount++; Console.WriteLine(fCount); };

My instinct tells me it is something simple and not a mistake, but I don't know enough about these expressions to understand why this is being done.

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

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

发布评论

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

评论(6

も让我眼熟你 2024-08-31 18:38:31

看起来他认为这相当于:

var eh = new EventHandler(delegate(object o, EventArgs e)
    { fCount++; Console.WriteLine(fCount); };

foo.MyEvent += eh;

foo.MyEvent -= eh;

但是取消注册不会按预期工作,因为它无法知道它应该引用注册的代表。

他用于添加处理程序的语法只是将匿名委托附加到事件的一种较短方法,并且是非常流行的语法,但如果您还必须取消注册它,我不建议使用它。

It looks like he's thinking that's equivalent to:

var eh = new EventHandler(delegate(object o, EventArgs e)
    { fCount++; Console.WriteLine(fCount); };

foo.MyEvent += eh;

foo.MyEvent -= eh;

But the unregistering isn't going to work as expected since it has no way of knowing its supposed to be referring to the registered delegate.

The syntax he's using for adding the handler is just a shorter way of attaching an anonymous delegate to an event and is pretty popular syntax, but not something I'd recommend using if you also have to unregister it.

夜声 2024-08-31 18:38:31

Lambda 表达式是声明函数的语法简写。因此,

(o, e) => { fCount++; Console.WriteLine(fCount); }

意味着一个带有两个参数并执行两个语句的函数。

至于代码片段,取消订阅'-='将不起作用,因为它是以下内容的简写:

foo.MyEvent += new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );
foo.MyEvent -= new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );

这实际上是资源泄漏。相反,存储对处理程序的引用并使用它来执行订阅和取消订阅:

var handler = new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );
foo.MyEvent += handler;
foo.MyEvent -= handler;

Lambda expressions are a syntactic shorthand to declare a function. So,

(o, e) => { fCount++; Console.WriteLine(fCount); }

means a function that takes two arguments and executes two statements.

As for the code snippet, the unsubscribe '-=' will not work because it is shorthand for:

foo.MyEvent += new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );
foo.MyEvent -= new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );

This is actually a resource leak. Instead store a reference to the handler and use that to perform the subscribe and unsubscribe:

var handler = new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );
foo.MyEvent += handler;
foo.MyEvent -= handler;
眼前雾蒙蒙 2024-08-31 18:38:30

lambda 表达式 (o, e) => { fCount++; Console.WriteLine(fCount); } 被解释为带有两个参数 o, e匿名方法(其类型是从用于 MyEvent 的委托类型推断出来的) > 并返回void 捕获封闭方法主体中的 fCount 变量(如果它是局部变量)。+= 运算符将捕获该变量。订阅事件的匿名方法,-= 取消订阅事件的委托


更新(关于委托实例相等性的问题):

重要的是要知道尝试取消订阅不是一个好主意。语言规范允许,但不要求第二行中的委托等于第一行中的委托。也就是说,允许编译器将两个匿名函数体视为相同。是否是同一个函数,或者不是(因为匿名函数体在语义上是相同的,并且捕获的变量集也相等)。即使它在编译器中按预期工作,它也可能在下一版本中崩溃。引用 C# 语言规范:

C# 语言规范(第 7.9.8 节委托相等运算符):

通过对具有相同(可能为空)捕获的外部变量实例集的语义相同的匿名函数表达式进行评估而生成的调用列表条目允许(但不要求)相等。

如果编译器将两个匿名函数表达式视为相等,则第二行将从事件中取消订阅前一个匿名方法。如果没有,第二行将不会执行任何特殊操作(如果列表中尚不存在委托,则从事件调用列表中取消订阅委托并不是错误)。

The lambda expression (o, e) => { fCount++; Console.WriteLine(fCount); } is interpreted as an anonymous method that takes two arguments o, e (whose types are inferred from the delegate type used for MyEvent and returns void. It captures the fCount variable in the body of the enclosing method (if it's a local variable). The += operator will subscribe the anonymous method to the event and the -= unsubscribes a delegate from an event.


Update (re: concerns about delegate instance equality):

It's important to know that it's not a good idea to try to unsubscribe from the event like that. The language specification, permits, but doesn't require that the delegate in the second line to be equal to the delegate from the first line. That is, the compiler is allowed to treat the two anonymous function bodies as if it was the same function or if it wasn't (because the anonymous function body is semantically identical and the set of captured variables is equal too). Even if it works as expected in your compiler, it might break in the next version. To quote the C# Language Specification on that:

C# Language Specification (Section 7.9.8 Delegate equality operators):

Invocation list entries produced from evaluation of semantically identical anonymous-function-expressions with the same (possibly empty) set of captured outer variable instances are permitted (but not required) to be equal.

If the compiler treats the two anonymous function expressions as equal, the second line will unsubscribe the previous anonymous method from the event. If it doesn't the second line will not do anything special (it's not an error to unsubscribe a delegate from an event invocation list if it doesn't already exist in the list).

梦与时光遇 2024-08-31 18:38:30

此处是有关 C# 中 lambda 表达式的精彩视频。该视频已有 2 年历史,但它可以让用户快速了解当时相对较新的功能。您感兴趣的内容从 3:02 左右开始。

Here is a great video about lambda expressions in C#. The video is 2 years old, but it gets users up to speed on the functionality that was relatively new at that time. The content you're interested begins around 3:02.

初雪 2024-08-31 18:38:30

这是一个错误。它向 MyEvent 事件添加匿名委托,但尝试删除同一匿名委托的不同实例。由于实例可能总是不同,因此它可能永远不会真正删除原始委托,这几乎肯定不是您想要的。

It is a mistake. It's adding an anonymous delegate to the MyEvent event, but trying to remove a different instance of the same anonymous delegate. Since the instance is probably always different, it may never actually remove the original delegate, which is almost certainly not what you want.

季末如歌 2024-08-31 18:38:30

它是使用 lambda 表达式的事件处理程序的实现。优点是它是a)内联的,即不需要额外的函数声明,b)它可以利用在您找到此声明的函数中声明的变量(使用闭包)。

It is an implementation of an event handler using a lambda expression. The advantag is that it is a) inline, i.e. no additional function declaration is required and b) that it can draw on the variables declared in the function where you found this declaration (using closures).

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