本文介绍了编译错误:+ =不能应用于事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有简化的代码:

I have the code, simplified:

class UserActionEventArgs : EventArgs { }
class CompilationEventArgs : UserActionEventArgs { }

class UserControl
{

   UserControl()
   {
      UserActionRequested += UserActionHandler;
      UserActionRequested += CompilationHandler;
      // error: Operator += cannot be applied
   }

   event EventHandler<UserActionEventArgs> UserActionRequested;

   void UserActionHandler(object sender, UserActionEventArgs eventArgs) {}
   void CompilationHandler(object sender, CompilationEventArgs eventArgs) { }

}



我不能编译这个.编译错误:运算符+ =不能应用于类型为``System.EventHandler< UserActionEventArgs>''的操作数.
为什么?! CompilationHandler怎么了?如果它可以处理参数CompilationEventArgs,则它始终可以处理参数UserActionEventArgs,因为UserActionEventArgsCompilationEventArgs的基类,而不是相反.



I cannot compile this. Compilation error: Operator += cannot be applied to operands of type ''System.EventHandler<UserActionEventArgs>''.

Why?! What''s wrong with CompilationHandler? If it can process argument CompilationEventArgs, it can always process argument UserActionEventArgs, because UserActionEventArgs is the base class for CompilationEventArgs, not the other way around.

推荐答案

class UserActionEventArgs : EventArgs { }
    class CompilationEventArgs : UserActionEventArgs { }
    class UserControl
    {
        UserControl()
        {
            UserActionRequested += UserActionHandler;
            UserActionRequested += CompilationHandler;
            // error: Operator += cannot be applied
        }
        event EventHandler<CompilationEventArgs> UserActionRequested;
        void UserActionHandler(object sender, UserActionEventArgs eventArgs) { }
        void CompilationHandler(object sender, CompilationEventArgs eventArgs) { }
    }


void Test() {
    UserActionEventArgs userAction = new UserActionEventArgs();
    CompilationEventArgs complilationAction = new CompilationEventArgs();    

    //valid: base <- derived
    userAction = complilationAction;

    //invalid: derived <- base
    //complilationAction = userAction;
} //Test



我添加了箭头以及"base"和"derived"注释,使图片成为"graphical".

所有正确的赋值从右到左进行,因此基类只能在左上.现在,为什么?
让我们在派生类中添加一些成员:



I added arrows and "base" and "derived" comment to make a picture "graphical".

All correct, assignment goes right-to-left, so base class can be only on left. Now, why?
Let''s add some member in the derived class:

class CompilationEventArgs : UserActionEventArgs { int myField; }



如果可以进行第二次赋值,则派生类的实例将尝试使用不存在的myField进行单词处理(甚至更糟糕的是将其称为不存在的方法).这是不允许的.

现在,添加事件的情况看起来相反:



If second assignment was possible, the instance of derived class would try to word with myField which does not exist (even worse to would be call non-existing method). This should not be allowed.

Now, the situation with adding of the event looks the opposite:

UserControl() {
    //valid:    derived <- base
    UserActionRequested += UserActionHandler;

    //invalid       bases <- derived
    //UserActionRequested += CompilationHandler;
    // error: Operator += cannot be applied
} //UserControl



好吧,这是因为事件参数类型的对象的分配是按照与上图所示相反的方向完成的,但又是按照第一个示例中显示的方向进行的(您似乎很了解).

首先,请考虑如何触发事件:



Well, this is because the assignment of the objects of event argument types in done in the direction opposite to the shown above, but again in the direction shown in first sample (which you seemingly understand).

First, consider how you fire the event:

void FireUserAction() {
    if (UserActionRequested != null)
        UserActionRequested(this, new UserActionEventArgs());
} //Fire



想象一下,您可以添加使用事件参数的派生类型而不是基本类型的句柄:



Imagine for a second that you could add your handle working with the derived type of event argument rather than the base type:

void CompilationHandler(object sender, CompilationEventArgs eventArgs) {
    //now to work with the actual parameter if
    //run-type type of it is of base class?! 
}



想象一下,该代码以某种方式被调用.这意味着将派生类型的变量分配给基本运行时类型的值. eventArgs的实际参数将尝试与字段myField一起使用(因为形式参数是该成员所在的派生类型),但是在运行时该成员不存在,因为形式(编译时) )参数为基本类型,该成员不存在.这就是为什么编译器不允许首先添加此事件处理程序的原因.
我希望这能解决您的困惑.

—SA



Imagine that this code is called somehow. It means assignment of the variable of derived type to the value of the base run-time type. The actual parameter of eventArgs would try to work with the field myField (because formal parameter is of the derived type where this member exists), but during run-time this member does not exists, because the formal (compile-time) parameter is of the base type, where this member does not exist. That''s why the compiler will not allow adding this event handler in first place.

I hope this will resolve your confusion.

—SA



这篇关于编译错误:+ =不能应用于事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 03:55