简体   繁体   中英

What are the benefits of having events conforming to Net guidelines?

I understand how to use Events according to Net Framework guidelines, but what are the benefits of using this pattern?

http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx :

The .NET Framework guidelines indicate that the delegate type used for an event should take two parameters, an "object source" parameter indicating the source of the event, and an "e" parameter that encapsulates any additional information about the event. The type of the "e" parameter should derive from the EventArgs class. For events that do not use any additional information, the .NET Framework has already defined an appropriate delegate type: EventHandler.

a) I see some benefits in using "object source" value as a first parameter since there are situations where multiple objects can have their events set to the same method. Thus, if for example we have 10 objects and if all 10 objects set their events to event handler M, then inside M we can use “object sender” parameter value to identify the initiator of the event call.

  • But as far as I can tell, ”object source” parameter is only useful if event was raised inside an instance method. Thus, if event was raised inside static method, then “object source” parameter is of no use?!

b) Are there other benefits of using events with accordance to Net Framework guidelines?

c) Whatever the benefits may be, why would they out-weight the trouble of having to

  • write an additional code to put the desired arguments into an object derived from EventArgs
  • write an additional code inside event handlers to extract information from object derived from EventArgs ?

thank you

As far as I see it there are two major benefits:

  • People writing code consuming the event will recognize the pattern and immediately know how to use the event
  • The signature of the event is crafted in a way that it is robust towards change

The first point should be pretty obvious, not needing a lot of elaboration.

As for the second point, there are two reasons for this (in my opinion). First, since sender is object , the event signature can be reused by several types. Second, since the second parameter is an EventArgs decendant, when you introduce your own EventArgs class this class can be extended later without altering the signature of the event.

Update
Response to questions:

I'm not sure what you mean by “ being able to extend EventArgs without altering the signature of the event”?!

Let's take an example, take the following class:

public class SomeClass
{
    public event EventHandler<FileEventArgs> SomethingHappened;
}
public class FileEventArgs : EventArgs
{
    public FileEventArgs(string filename)
    {
        Filename = filename;
    }
    public string Filename { get; private set; }
}

Then we have a consumer that listens to the SomethingHappened event:

static void SomethingHappenedHandler(object sender, FileEventArgs e)
{
    // do something intelligent
}

Now, lets say that we want to extend the information that we transfer in the event with information about what happened to the file:

public enum WhatHappened
{
    Copy,
    Rename,
    Delete
}
public class FileEventArgs : EventArgs
{
    public FileEventArgs(string filename, WhatHappened whatHappened)
    {
        Filename = filename;
        WhatHappened = whatHappened;
    }
    public string Filename { get; private set; }
    public WhatHappened WhatHappened { get; private set; }
}

Now, if we had chosen to send the filename as a parameter in the event itself, we would need to alter the event signature by adding another parameter, effectively breaking all code that listens to the event. But since we in the code above have simply just added another property to the FileEventArgs class, the signature remains unchanged, and no listeners need to be updated (unless they want to use the newly added property, that is).

Am I write in assuming that if event is raised inside static method, then “object source” parameter is of no use?!

Yes, that is correct. I typically pass null as the sender argument from static events (which, honestly, is very rare).

If you adhere to the .NET Framework guidelines, not only for events, but for everything, someone who needs to read your code or use your library will recognize it, making things simpler for him. This is always a good thing, since you should write code for your readers, not for your convenience. The good thing with .NET is that there is some standard guideline right from the beginning, in contrast to the thousands of conventions for C++ and the like, and most people know it and apply it.

The added benefit of the standard event handler signature is that you can assign less specialized event handlers (like, say, EventHandler ) to an event of a more specialized type, simplifying development if someone does not need the additional data. It also makes it simpler to add event handlers via Reflection, which may be useful in certain circumstances (like an object hierarchy browser for some object model) - I can assure you that code to handle any event via Reflection is a complicated thing which I solved by emitting IL code for each event, which I'd always regard as a last resort.

As Fredrik Mörk wrote in the mean time, this makes it also easier to extend your event later by adding parameters just to your EventArgs-derived class, rather than to each and every event handler.

Well one of the main benefits of a standard approach is the fact that it does what it says on the tin. A standard approach means that any developer looking at your code immediately gets what is going on, and how to use your events.

personally, I don't follow this guideline all the time, only for work that will be published for general reuse

why?

  • because i don't always need to know the sender of an event
  • because moving the delegate arguments - especially when there's only one - to a separate class is overkill

yes, i know, the arguments may change in the future. But YAGNI. And frankly, when I do have to change the arguments in an event delegate, the compiler conveniently tells me every place that used it so I can check that they handle the new parameters correctly. If i had followed the standard and used a custom EventArgs class, I'd have to search out these places manually.

so, as usual, "it depends" and "use your own judgement" apply :-)

You can use Generic Event Handler delegate (EventHandler< TEventArgs >) if you use standard event signatures and your event arguments inherit from eventargs.

public event EventHandler<MyCustomEventArgs> MyEvent;

http://msdn.microsoft.com/en-us/library/db0etb8x.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM