tags:

views:

155

answers:

4

Assuming we declare a class DerivedEventArgs:

public class DerivedEventArgs : EventArgs { ... }

then EventHandler delegate is able to accept methods with the following signature:

public static void Some_Method(object o, DerivedEventArgs e) { ... }

But if we try to subscribe a method with the above signature to the event implementing EventHandler delegate:

public event EventHandler MyEvent;

, then we get an error. Why is that?

thanx

+2  A: 

Suppose the code raising the event specified a value which wasn't a DerivedEventArgs - what would you expect it to do? Basically you'd lose type safety.

EDIT Note that you can do it the other way round - you can subscribe to an event with a more specific parameter type using a method with a less specific parameter type - because the event is still guaranteeing that it will call the handler with something compatible. Here's an example:

using System;

class Test
{
    public class DerivedEventArgs : EventArgs { }

    public EventHandler<DerivedEventArgs> SpecialistEvent;

    static void Main()
    {
        Test t = new Test();
        t.SpecialistEvent += GeneralHandler;
    }

    static void GeneralHandler(object sender, EventArgs e)
    {
    }
}
Jon Skeet
first I was going to argue why then can EventArgs delegate accept this method, but then when I've again tried this in code, I got an error, even thought the first time compiler didn't complain ( I've probably messed up the code the first time ).So it seems EventArgs delegate also won't accept this method
AspOnMyNet
"Basically you'd lose type safety." Same argument could be said about method parameters of class of type A being able to accept arguments of types derived from A
AspOnMyNet
No, not really. It's sought of the reverse. You're asking that a less derived type argument sent to you be always treated as your more derived type without casting when your handler is called.
kervin
@AspOnMyNet: The point is that you can convert the argument from the *more specific* type to the *less specific* type, but not the other way round. If my method accepts a parameter of type "TextReader" then it can cope with any kind of TextReader - e.g. a StreamReader. The reverse *isn't* true. Suppose your method is declared as accepting StreamReader and someone passes you a StringReader - what would happen when you tried to find the underlying stream?
Jon Skeet
i see your point. thank you all for helping me
AspOnMyNet
+2  A: 
MyEvent(this, EventArgs.Empty)

would try to pass a regular EventArgs to DerivedEventArgs in

Some_Method(object o, DerivedEventArgs e) 

and then if Some_Method tried to do an

e.PropertyInDerivedClass

it'd fail.

Tanzelax
+2  A: 

try using an EventHandler<T> for your event, where T is your DerivedEventArgs class.

Tony
@AspOnMynet: the EventHandler<DerivedEventArgs> event will try to pass (object, DerivedEventArgs) to its methods, and you can pass a DerivedEventArgs to a method expecting EventArgs.
Tanzelax
Uhm, this is a bit confusing. Event implementing EventHandler<DerivedEventArgs> is also able to accept methods with signature void Some_Method(object o, EventArgs e)? How is that possible? I do get a runtime exception though, but it's weird compiler didn't report the error during compilation time
AspOnMyNet
it turned out that something else in my code was causing an exception.Thanx for helping me mate
AspOnMyNet
A: 

From MSDN EventHandler documentation...

EventHandler is a predefined delegate that specifically represents an event handler method for an event that does not generate data. If your event does generate data, you must supply your own custom event data type and either create a delegate where the type of the second parameter is your custom type, or use the generic EventHandler< TEventArgs > delegate class and substitute your custom type for the generic type parameter.

The EventHandler Delegate was not made to do what you're trying to do. It's a simple convenience delegate for use in cases where event data is unimportant. The event that utilizes this delegate type may send a EventArgs with the least derived event argument type possible. That means your delegate should be ready to receive anything.

But in your example, you're specifying a more derived event argument type in your handler. Hence, if allowed by the compiler, your code can actually receive another EventArgs type that's not what you expect but defined as your derived type; breaking type safety as mentioned earlier.

kervin
Crap, I tried to give you a point but it seems I've instead voted you down.I'm really sorry about that
AspOnMyNet
lol, that's not a problem. Hope the post helped.
kervin
it sure did, thanx
AspOnMyNet