13

When I write public events for my business objects, I've adapted the habit of always passing the instance as "sender as Object", in addition to additional specific parameters. I just asked myself now why am I not specifying the class?

So for you with more experience; Do you ever pass the distinct class as sender in an event? And if so, what are your decision criteria for when this is ok/not ok?

bretddog
  • 5,411
  • 11
  • 63
  • 111
  • If you have to ask "why don't I", you really shouldn't do it. The guidelines on how to create event signatures were designed like they are for a reason. At least go read up on those reasons before deciding to deviate from them just because you can. – Lasse V. Karlsen Feb 09 '11 at 12:16
  • Think about it: What if later you consider that your event fits elsewhere, and you want to raise it from another point in your code. Would it be the same sender class? Not if you specify the sender's type... – Smur Feb 09 '11 at 12:19
  • 1
    @Lasse: I could just as well ask "why do I?". I was not aware it was a guideline for this, I'm not a pro-programmer. Still as there is a guideline, I would like to know if it's common or very rare to break this guideline or not. – bretddog Feb 09 '11 at 12:21
  • http://stackoverflow.com/questions/3220504/creating-custom-events-object-sender-or-typed-sender http://stackoverflow.com/questions/1046016/event-signature-in-net-using-a-strong-typed-sender – CodesInChaos Feb 09 '11 at 12:24
  • @Felipe: I've never shared an event between different sender classes. But maybe that's a practice I can learn and benefit from. – bretddog Feb 09 '11 at 12:24
  • It is very uncommon to deviate from those guidelines. – Lasse V. Karlsen Feb 09 '11 at 12:24
  • This question is a duplicate of [Event signature in .Net - using a strongly typed sender?](http://stackoverflow.com/questions/1046016/event-signature-in-net-using-a-strong-typed-sender) – MarkJ Feb 09 '11 at 13:16
  • @LasseV.Karlsen Here's what Microsoft now says about this: "Generic delegates are especially useful in defining events based on the typical design pattern because the sender argument can be strongly typed and no longer has to be cast to and from Object". http://msdn.microsoft.com/en-us/library/sx2bwtw7.aspx – d7samurai Oct 04 '13 at 01:32
  • Yep, so the guidelines have changed. – Lasse V. Karlsen Oct 04 '13 at 06:59

8 Answers8

11

Don't be extreme. EventHandler(object sender, EventArgs e) has an object sender so that we can use it in many circumstances. But it doesn't mean a strongly-typed sender is evil. A strongly-typed sender is useful when this delegate is not going to be widely used(like EventHandler) e.g.

public delegate void SaveHandler(Controller sender, EventArgs e);

Now other developers(or someone using your library) can recogonize that the sender have to be a Controller, and they will be glad not to code like this:

public void MySaveHandler(object sender, EventArgs arg)
{
   var controller = sender as Controller;
   if (controller != null)
   {
       //do something
   }
   else
   {
       //throw an exception at runtime? 
       //It can be avoided if sender is strongly-typed
   }
}

And you can even make it generic:

public delegate void SaveHandler<T>(T sender, EventArgs args) 
                                              where T: IController;

It's pure legal and good practice in C#. You should make clear what you want to do, and then choose the better way. Either of them is evil/bad.

Cheng Chen
  • 42,509
  • 16
  • 113
  • 174
5

There is a design guideline that specified that an event-handler should have two params: sender (an Object) and e (EventArgs or derived from that).

Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
  • 1
    +1: Personally I consider the best advice here. The guidelines aren't rules or laws. You *can* deviate from them, but before you do that you really should know why they were created in the first place, what sort of problems or situations they try to manage, and what your alternatives are. Deviating just because you can is never a good reason. – Lasse V. Karlsen Feb 09 '11 at 12:15
  • 2
    @Lasse: actually, I doubt there was a valid (or at least "good enough") reason they opted for this, except that there were no generics in the first version of .NET. – vgru Jan 11 '12 at 11:59
  • @Groo: I seem to remember reading on one of the MSDN blogs a while ago that this is exactly the reason why the design decision was taken to have the sender parameter typed as an object. Just one of those things that has now become such a well established convention that people expect it in public APIs. Absolutely no reason why the parameter shouldn't be strongly or generically typed if it isn't exposed publicely though. – 0b101010 Feb 03 '15 at 17:01
1

There no such restriction. It is just a guideline that is followed throughout BCL (Base Class Library) and other popular frameworks.

I would recommend you follow it to keep it consistent if it is going to be used by other developers or be released as a framework.

decyclone
  • 30,394
  • 6
  • 63
  • 80
1

As far as I see it you can either create delegates with the parameters you want and then create an event using that delegate and then you can call the event and pass the parameters in or you can use Custom Event Argument as shown here. As the other answer suggests. Keep it consistent.

Doesn't really answer your question about the decision criteria but hope it helps

Jon
  • 38,814
  • 81
  • 233
  • 382
1

My current philosophy is to keep code practices as close to the standard Microsoft way as possible. You get two things from this:

  • New developers can quickly understand your code
  • You train existing developers how the rest of the framework works
djeeg
  • 6,685
  • 3
  • 25
  • 28
1

It is good practice to use the object sender, EventArgs e signature, as the method can handle any events of that signature. For example, in a project using a charting control, there are several types of MouseOver events - from a DataSeries, from the Legend, from the whole Canvas.

That way, you can handle any source of the event, as at most times, the information is in the EventArgs.

Also, you don't have to cast the sender when passing it to the delegate, as any class instance is an object deep down.

Femaref
  • 60,705
  • 7
  • 138
  • 176
  • 4
    I don't think this is relevant. The client code could still handle the event through a method with the sender typed as `object`, even if the event is declared with a more strongly-typed sender. [Contravariance](http://stackoverflow.com/questions/1046016/event-signature-in-net-using-a-strong-typed-sender). – MarkJ Feb 09 '11 at 13:19
1

There was a lot of discussion on a related question on StackOverflow some time ago. Here is that question: Event Signature in .NET -- Using a strong-typed sender

Eventually, it comes down to preference. In most cases, you'd like your event handlers to be bound to a particular type of class so making the sender an object and then casting back to the class in order to get access to its properties might not go down well with you [it doesn't go down well for me either].

Besides, with .NET 3+ and the introduction of delegate covariance and contravariance, it should not be a problem to use a strongly typed delegate. I must admit, I've used strongly typed event handlers more than once in my code.

Like I said earlier, it comes down to preference; Microsoft just issued a set of guidelines not rules...

Community
  • 1
  • 1
Alex Essilfie
  • 12,339
  • 9
  • 70
  • 108
0

It is not a binding on you to have such implementation. Its usually done because of the EventHandler delegate was designed with such prototype.

Its a simple guideline followed through Base Class Library. But sure you can make you own Parameters and implementations.

But remember if it is to be used by some developer other that you, he will need to know about such implementation. Its don for greater good and flexibility to use an event anywhere irrespective of class its used in.

If you define a Custom Prototype for event then i would suggest that you also define Custom Delegate that will ensure you will have catch an exception if proper type is not passed. (User will need to do an Explicit cast if required)

Like this:

public delegate void MyEventHandler( MyType sender, EventArgs e);

Then use it where required as:

this.MyEvent += new MyEventHandler(my_eventhandlerfunction);
Shekhar_Pro
  • 18,056
  • 9
  • 55
  • 79