Click here to Skip to main content
Click here to Skip to main content

Generic EventHandler/EventArgs with a Generic Implicit Cast Operator

By , 10 Jan 2013
Rate this:
Please Sign up or sign in to vote.

Introduction

This is an idea I had a few days back. While most of you out there will know how to create and use a generic EventHandler and/or generic EventArgs, it's that spicy little implicit cast operator that made me write this down for you.

I hope you find a little bit of useful information here.

Please leave me a note telling me if you already had the same idea that's shown here.

Background

We all have created EventHandlers and have derived EventArgs for lots of different reasons. I have used a generic implementation for years but was not really happy with the code, how it looked like... There were just too many brackets involved, especially when raising the event with a line like:

OnMyEvent(new GenericEventArgs<Dictionary<int, List<string>>>(myDic));

It would have been much nicer to raise the event just with:

OnMyEvent(myDic);

YES of course, I could just create an On... method that takes the Dictionary directly, but I didn't want that, as the protected virtual void OnEventName(EventArgs e) method signature is a standard, and I don't like to break standards.

That's how I came to the idea. I will show you now.

Create a Generic EventHandler and EventArgs

Let's start with a generic EventHandler and EventArgs that will allow us to forward one single Data Item with the event. This is enough for most cases, as we can easily deliver a class or data holder of any kind with all the details that need to be delivered with the event.
(Comments are skipped here but in the downloadable file, everything is XML-commented of course):

public class ItemEventArgs<T> : EventArgs
{
    public ItemEventArgs(T item)
    {
        Item = item;
    }
 
    public T Item { get; protected set; }
}

The EventHandler for this is simple and straightforward, too:

public delegate void ItemEventHandler<T>(object sender, ItemEventArgs<T> e);

So now, we can declare any event that shall deliver one single item of data/information as follows (I take this from a real code where I use that delegate in a UDP communication class):

public event ItemEventHandler<DataPacket> PacketReceived;

and the protected method to raise the event is completely standard, too:

protected virtual void OnPacketReceived(ItemEventArgs<DataPacket> e)
{
    if (PacketReceived != null) PacketReceived(this, e);
}

From my code, I could raise the event now as:

OnPacketReceived(new ItemEventArgs<DataPacket>(_packet));

It's this new ItemEventArgs<DataPacket> that I didn't like too much, I preferred a call like:

OnPacketReceived(_packet);

without having to declare a On... method that takes a packet directly. So I tried an implicit cast operator, wondering if this would work generic. And it does!
So, if you never did a cast operator like this, it will be new information for you, and I really had an "ahaaaaa!" effect when I found that out, and this is the reason for sharing it with you.

I put that cast operator in the ItemEventArgs<T> class, and it did what I was really hoping for:

public static implicit operator ItemEventArgs<T>(T item)
{
    return new ItemEventArgs<T>(item);
}

This little gem allowed me, from now on to call any of my On... methods that work with the generic ItemEventargs to be called directly with the object to deliver, and to skip the new ItemEventArgs<T>(...) from now on.
The raising code in my UDP class (and many other classes) now really looks like:

OnPacketReceived(_packet);

without ever having to declare another On... method that would break what is considered as "standard". Inheritors still find their common expected virtual method to override, but the callers can use it in a more readable way.

This generic implicit cast is not limited by the virtual On... methods. ANY call, that expects ItemEventArgs<T> can now be done directly without having to instantiate the <T> class! You can do implicit generic casts like that for any class you make. Hope this gives you a new idea or two!

I discussed this with some colleagues here in the office and they all liked the idea because the code is more beautiful to read.

So if you didn't have the idea of a generic implicit cast operator so far, I hope you will take this for your own use.

Cheers,
Mike

History

  • 2013-01-11 Published

License

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

About the Author

Mike Barthold
Software Developer (Senior)
Austria Austria
Software Developer since the late 80's, grew up in the good old DOS-Era, switched to windows with Win95 and now doing .net since early 2002 (beta).
Long year c# experience in entertainment software, game programming, directX and XNA as well as SQLServer (DBA, Modelling, Optimizing, Replication, etc) and Oracle Databases in Enterprise environments.

Comments and Discussions

 
GeneralMy vote of 5 Pinmemberishihidul14-Jan-13 12:05 
GeneralRe: My vote of 5 PinmemberMike Barthold14-Jan-13 18:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140415.2 | Last Updated 11 Jan 2013
Article Copyright 2013 by Mike Barthold
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid