当前位置:  开发笔记 > 编程语言 > 正文

lambda表达式中的事件 - C#编译器错误?

如何解决《lambda表达式中的事件-C#编译器错误?》经验,为你挑选了1个好方法。

我正在寻找使用lamba表达式来允许事件以强类型方式连接,但是在中间有一个监听器,例如给定以下类

class Producer
{
    public event EventHandler MyEvent;
}

class Consumer
{
    public void MyHandler(object sender, EventArgs e) { /* ... */ }
}

class Listener
{
    public static void WireUp(
        Expression> expr) { /* ... */ }
}

事件将被连线为:

Listener.WireUp((p, c) => p.MyEvent += c.MyHandler);

但是这会给编译器错误:

CS0832:表达式树可能不包含赋值运算符

现在起初这似乎是合理的,特别是在阅读了关于为什么表达式树不能包含赋值的解释之后.但是,尽管有C#语法,但+=它不是赋值,它是对Producer::add_MyEvent方法的调用,正如我们可以从CIL中看到的那样,如果我们只是正常连接事件:

L_0001: newobj instance void LambdaEvents.Producer::.ctor()
L_0007: newobj instance void LambdaEvents.Consumer::.ctor()
L_000f: ldftn instance void LambdaEvents.Consumer::MyHandler(object, class [mscorlib]System.EventArgs)
L_0015: newobj instance void [mscorlib]System.EventHandler::.ctor(object, native int)
L_001a: callvirt instance void LambdaEvents.Producer::add_MyEvent(class [mscorlib]System.EventHandler)

因此,我认为这是一个编译器错误,因为它抱怨不允许分配,但没有任何分配,只是一个方法调用.或者我错过了什么......?

编辑:

请注意,问题是"此行为是编译器错误吗?".对不起,如果我不清楚我在问什么.

编辑2

在阅读了Inferis的回答之后,他说"在那一点上+ =被认为是赋值"这确实有意义,因为此时编译器可能无法知道它将变成CIL.

但是我不允许编写显式方法调用表单:

Listener.WireUp(
    (p, c) => p.add_MyEvent(new EventHandler(c.MyHandler)));

得到:

CS0571:'Producer.MyEvent.add':无法显式调用operator或accessor

所以,我想这个问题归结为+=C#事件的实际意义.这是否意味着"为此事件调用add方法"或它是否意味着"以尚未定义的方式添加到此事件".如果它是前者,那么在我看来这是一个编译器错误,而如果它是后者那么它有点不直观但可以说不是一个bug.思考?



1> Jon Skeet..:

在7.16.3节的规范中,+ =和 - =运算符被称为"事件赋值",它肯定使它听起来像赋值运算符.它在7.16节("赋值运算符")中的事实是一个非常大的暗示:)从这个角度来看,编译器错误是有道理的.

然而,我同意这过于严格,因为它是完全有可能的表达式树来表示由lambda表达式给定的功能.

怀疑语言设计师采用"稍微限制但操作员描述更一致"的方法,牺牲了这样的情况,我担心.

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有