Click here to Skip to main content
15,894,955 members
Please Sign up or sign in to vote.
1.33/5 (3 votes)
See more:
I have the code, simplified:

C#
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) { }

}


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.
Posted
Updated 4-Jan-11 12:04pm
v3
Comments
Manfred Rudolf Bihy 5-Jan-11 8:04am    
Well, you also thaught me a valuable lesson. If I'm not really sure about what I'm saying I'll just try it out first before posting it here. So long!

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:
C#
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) { }
    }
 
Share this answer
 
v5
Comments
programmer095 4-Jan-11 21:20pm    
Surprised. This is just the opposite to my explanation. I though it will not compile and I did not understood why my variant did not compile.
I still don't understand.

Anyway, I'll think if I can use it. Thank you very much. It would be good to undestand why.
You rock! (unlike others)
jerrykid 4-Jan-11 21:28pm    
To make you understand clearly about why the compiler cannot compile the whole codes you gave. I think you need to read more documents about inheritance. These are some references:
http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)
http://www.csharp-station.com/Tutorials/lesson08.aspx
programmer095 4-Jan-11 21:34pm    
Oh, that's great!
I think I just need to think. You gave me enough food for though for now.

Thank you so much!
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:

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

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

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


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:

C#
class CompilationEventArgs : UserActionEventArgs { int 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:

C#
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:

C#
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:

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


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
 
Share this answer
 
v3
Comments
programmer095 6-Mar-11 21:59pm    
Finally! Understand. Accepted.
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());

}
 
Share this answer
 
v3
Comments
programmer095 4-Jan-11 18:44pm    
I don't know. Why mode code is not working?
programmer095 4-Jan-11 18:57pm    
Ok, I just tried it. It did not compile.

First, what's the difference? I explained why I don't understand why.

Second: why would you lie to me?!
I have a code with 12 lines only. After your advice I had to modify only one line.
Before answering you could type it and try.
I saw your answer will not work before I tried, because there is not difference. But I tried.
Thanks for try. But you know, lie is much worse then saying nothing.
I vote big fat 1.
DeliciousBiscuit 4-Jan-11 20:16pm    
Offering suggestions and including "I think" in the answer implies that he suggestion is not tested. Secondly, since the original suggestion was only one additional line of code and one change of type, it shouldn't be too hard to try it yourself. The code above compiles. Programming is stressful sometimes, try not to let it get to you.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900