我正在使用羔羊表达式来允许事件以强类型的方式进行连接,但是在中间有一个听众.给出以下类
- class Producer
- {
- public event EventHandler MyEvent;
- }
- class Consumer
- {
- public void MyHandler(object sender,EventArgs e) { /* ... */ }
- }
- class Listener
- {
- public static void WireUp<TProducer,TConsumer>(
- Expression<Action<TProducer,TConsumer>> expr) { /* ... */ }
- }
一个事件将被连线如下:
- Listener.WireUp<Producer,Consumer>((p,c) => p.MyEvent += c.MyHandler);
但是这会给出一个编译错误:
CS0832: An expression tree may not contain an assignment operator
现在起初这似乎是合理的,特别是在reading the explanation about why expression trees cannot contain assignments之后.然而,尽管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<Producer,Consumer>(
- (p,c) => p.add_MyEvent(new EventHandler(c.MyHandler)));
得到:
CS0571: ‘Producer.MyEvent.add’: cannot explicitly call operator or accessor
所以,我猜这个问题归结于C#事件背景下的实际意义.这是否意味着“调用此事件的添加方法”或是否意味着“以尚未定义的方式添加到此事件”.如果是前者,那么这似乎是一个编译器的bug,而如果它是后者,那么它有点不直观,但可以说是不是一个bug.思考?