编译错误:+ =不能应用于事件 [英] Compilation error: += cannot be applied to event

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

问题描述

我有简化的代码:

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.

推荐答案

您不能将父类分配给子类.如果您将孩子从父母分配给父母,那将是可以的.因此,您必须将事件更改为event EventHandler<CompilationEventArgs> UserActionRequested;
并尝试以下代码:
You cannot assign a parent class to child class. It will be OK if you assign from child to parent. So you must change the event into event EventHandler<CompilationEventArgs> UserActionRequested;
And try this code:
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) { }
    }


我将此问题添加为书签,但稍后回答,对此感到抱歉.

我认为您已经了解了基类实例和派生类实例之间的有效分配,这使您感到困惑.问题是:您机械地应用了一些学习到的规则,而没有试图理解原因.
考虑事件参数类之间的分配:

I bookmarked this Question but answering much later, sorry about that.

I think you have learned about valid assignment between the instance of base and derived classes, and that created you confusion. The problem is: you applied some learned rules mechanically without attempt to understand why.

Consider assignment between you event argument classes:

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


我认为,如果您定义一个继承自eventarg的抽象类,然后在更改事件声明以使用时基于该类定义两个eventargs类抽象类作为类型,那么它将起作用.

我认为编译器无法识别来自eventarg的继承链,这就是为什么它会抱怨.

我什至不确定您是否需要两个事件处理程序.您可以在处理程序中测试eventarg的类型,然后调用适当的函数,但是,我不知道您实际上要做什么.

试试这个

抽象类MyBaseEventArg:EventArgs {}
class UserActionEventArgs:MyBaseEventArg {
public int userproperty {get;放; }
}
class CompilationEventArgs:MyBaseEventArg {
public int compileproperty {放; }
}

类UserControl
{

UserControl()
{
UserActionRequested + = UserActionHandler;
UserActionRequested + = CompilationHandler;
//错误:运算符+ =不能应用
}

事件EventHandler< MyBaseEventArg> UserActionRequested;

void UserActionHandler(object sender,MyBaseEventArg eventArgs){
如果(eventArgs是UserActionEventArgs)
{
UserActionEventArgs er =(UserActionEventArgs)eventArgs;

int i = er.userproperty;
}
}

void CompilationHandler(object sender,MyBaseEventArg eventArgs){

如果(eventArgs是CompilationEventArgs)
{
ce =(CompilationEventArgs)eventArgs;

int i = ce.compileproperty;
}
}

公共无效userdidsomething()
{
//regularmode
UserActionRequested(this,new UserActionEventArgs());

//compilemode
UserActionRequested(this,new CompilationEventArgs());

}
I think if you define an abstract class that inherits from eventarg and then define your two eventargs classes based on that class while changing the event declaration to use the abstract class as the type then this would work.

I don''t think the compiler recognizes the chain of inheritance from eventarg and that is why it is complaining.

I''m not even sure you need two event handlers. You could test the type of the eventarg in your handler and then call the appropriate function, but then, I don''t know what you are really trying to do.

try this

abstract class MyBaseEventArg : EventArgs { }
class UserActionEventArgs : MyBaseEventArg {
public int userproperty { get; set; }
}
class CompilationEventArgs : MyBaseEventArg {
public int compileproperty { get; set; }
}

class UserControl
{

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

event EventHandler<MyBaseEventArg> UserActionRequested;

void UserActionHandler(object sender, MyBaseEventArg eventArgs) {
if (eventArgs is UserActionEventArgs)
{
UserActionEventArgs er = (UserActionEventArgs)eventArgs;

int i = er.userproperty;
}
}

void CompilationHandler(object sender, MyBaseEventArg eventArgs) {

if (eventArgs is CompilationEventArgs)
{
CompilationEventArgs ce = (CompilationEventArgs)eventArgs;

int i = ce.compileproperty;
}
}

public void userdidsomething()
{
//regularmode
UserActionRequested(this, new UserActionEventArgs());

//compilemode
UserActionRequested(this, new CompilationEventArgs());

}


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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆