views:

287

answers:

6

I hate EventHandler. I hate that I have to cast the sender if I want to do anything with it. I hate that I have to make a new class inheriting from EventArgs to use EventHandler<T>.

I've always been told that EventHandler is the tradition and blah, blah...whatever. But I can't find a reason why this dogma is still around.

Is there a reason why it would be a bad idea to make a new delegate:

delegate void EventHandler<TSender, T>(TSender sender, T args);

That way the sender will be typesafe and I can pass whatever the heck I want as the arguments (including custom EventArgs if I so desire).

+5  A: 

There is no reason to use it other than its the accepted .net convention and anyone reading your code should understand it fairly easily. For this it's a good reason.

However it's your code and you can decide what best for you. Of course as you interact with the fcl you will have to do it their way using event handlers.

Preet Sangha
I agree, it's accepted that any c# coder would recognise.
Vince
That being said, a strongly typed delegate would also be recognised :)
Vince
I don't see why developers would be confused by the OP's code. However, +1 for pointing out the obvious: it's his code to do with as he will.
Chris Lively
A: 

As Preet Sangha said, the reason why creating such a delegate would be a bad idea is that other developers could be confused why you doing it in that way.

Using EventHandler delegate is a guideline presented here: http://msdn.microsoft.com/en-us/library/ms229011.aspx

prostynick
You might argue, though, that if using, say, `Action<...>` as your event handler is enough to confuse a team member, your team has bigger problems already. ;)
jalf
+3  A: 

I commonly use Action<...> types as event handlers - if you don't need to interop with other code (or a designer) that specifically requires EventHandler, there's no reason to use it.

Eamon Nerbonne
+2  A: 

Well, doing all that casting is unusual, the client code quite often already knows who the sender is because it explicitly subscribed the event for only one object. Sharing event handlers is fairly rare. If common behavior is desirable then the better approach is to derive from the class and override the OnXxxx method. You then no longer care about sender, you got this.

But, solve your problem trivially by including a type-safe reference to the sender in your custom EventArgs derived class.

Hans Passant
+19  A: 

There actually is a good reason for requiring the second argument to derive from EventArgs if your fully-trusted code hosts third-party code as partially-trusted.

Because the callback to the event handling delegate is done in the context of the raising code and not the third party code, it is possible for malicious third-party code to add a privileged system operation as an event handler and thus potentially execute an escalation of privilege attack by running code in your fully-trusted context that their partially-trusted context could not run.

For example, if you declare a handler as type int -> void then the third-party code could enqueue YourEvent += Enviroment.Exit(-1) and have you exit the process unintentionally. This would obviously cause an easy-to-detect problem, but there are far more malicious APIs that could be enqueued to do other things.

When the signature is (object, EventArgs) -> void then there are no privileged operations in the framework that can be enqueued because none of them are compatible with this signature. It's part of the security code review in the framework to ensure this (unfortunately I cannot find the source where I read this).

So in certain circumstances there are valid security concerns as to why you should use the standard pattern. If you're 100% sure your code will never be used in these circumstances then the event signature guideline isn't as important (apart from other developers thinking WTF), but if it might be then you should follow it.

Greg Beech
+1 Wow. Nice post. This is the type of posts that keep me coming back to SO.
Chris Lively
Very very interesting. I love to know if this was in the original design or convention fell out or usage.
Preet Sangha
Though this is a valid answer with the current state of affairs, it seems it would be much better if code that shouldn't call Exit (or pass it through to be called) wasn't even be able to access Exit in the first place.
Roger Pate
I don't understand one thing. With `EventHandler` you can't do `YourEvent += EnvironmentExit`, but how about `YourEvent += (sender, args) => Environment.Exit(-1)`? Isn't that the same and `Exit` will be called in fully-trusted context?
prostynick
+1  A: 

I agree with you, the convention is stupid and/or antiquated. Do it the right way, with proper type safety and generics.

It comes up all the time that you have a task to do, and you can follow the way the last guy did it OR do it another way that you think is probably better.

The first choice is usually chosen -- do it the same as the last guy, and you won't get in trouble. But the second choice is what improves software over the long haul. (Or at least it CAN improve it, if you're right that your way is better! :) )

Scott Stafford