Click here to Skip to main content
11,804,008 members (78,991 online)
Click here to Skip to main content

Generic EventHandler/EventArgs with a Generic Implicit Cast Operator

, 22 Sep 2015 CPOL 12.7K 20
Rate this:
Please Sign up or sign in to vote.
Generic EventHandler/EventArgs with a generic implicit cast operator


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.


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:


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)
    PacketReceived?.Invoke(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:


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:


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.


For easier copying of the code, here it is, all in a single block:

using System;

namespace Mbi.Toolbox
    /// <summary>
    /// Generic EventHandler to be used with the generic EventArgs class <see cref="ItemEventArgs{T}"/>.
    /// </summary>
    /// <typeparam name="T">The item type contained in the <see cref="ItemEventArgs{T}"/>.</typeparam>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">The <see cref="ItemEventArgs{T}"/> instance containing the event data.</param>
    public delegate void ItemEventHandler<T>(object sender, ItemEventArgs<T> e);

    /// <summary>
    /// Generic EventArgs for Events that need to supply one parameter. For use with the generic EventHandler <see cref="ItemEventHandler{T}"/>.
    /// </summary>
    /// <typeparam name="T">The type of the parameter used in the EventArgs.</typeparam>
    public class ItemEventArgs<T> : EventArgs
        /// <summary>
        /// Initializes a new instance of the <see cref="ItemEventArgs{T}"/> class.
        /// </summary>
        /// <param name="item">The item to passed with the event.</param>
        public ItemEventArgs(T item)
            Item = item;

        /// <summary>
        /// Gets the item passed with this event.
        /// </summary>
        /// <value>
        /// The item passed with this event.
        /// </value>
        public T Item { get; protected set; }

        /// <summary>
        /// Implicitly converts an item of Type T to <see cref="ItemEventArgs{T}"/>.
        /// </summary>
        /// <param name="item">The item to convert.</param>
        /// <returns>
        /// A new instance of <see cref="ItemEventArgs{T}"/> containing the item.
        /// </returns>
        public static implicit operator ItemEventArgs<T>(T item) => new ItemEventArgs<T>(item);



  • 2013-01-11 Published
  • 2015-09-22 Updated the event invoke to the new C# 6.0 syntax.


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.

You may also be interested in...

Comments and Discussions

Questiongood article ! ... one question Pin
BillWoodruff23-Sep-15 20:59
mvpBillWoodruff23-Sep-15 20:59 
AnswerRe: good article ! ... one question Pin
Mike Barthold24-Sep-15 7:56
memberMike Barthold24-Sep-15 7:56 
QuestionNice touch Pin
daz201123-Sep-15 14:06
professionaldaz201123-Sep-15 14:06 
AnswerRe: Nice touch Pin
Mike Barthold23-Sep-15 18:25
memberMike Barthold23-Sep-15 18:25 
QuestionCannot compile using C# in VS 2013 Pin
BillKru23-Sep-15 10:53
memberBillKru23-Sep-15 10:53 
AnswerRe: Cannot compile using C# in VS 2013 Pin
Mike Barthold23-Sep-15 18:23
memberMike Barthold23-Sep-15 18:23 
GeneralRe: Cannot compile using C# in VS 2013 Pin
BillKru23-Sep-15 21:46
memberBillKru23-Sep-15 21:46 
Question.Net EventHandler<T> Pin
bcd21-Sep-15 11:33
memberbcd21-Sep-15 11:33 
AnswerRe: .Net EventHandler<T> Pin
Mike Barthold21-Sep-15 18:33
memberMike Barthold21-Sep-15 18:33 
GeneralMy vote of 5 Pin
ishihidul14-Jan-13 12:05
memberishihidul14-Jan-13 12:05 
GeneralRe: My vote of 5 Pin
Mike Barthold14-Jan-13 18:52
memberMike 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 | Terms of Use | Mobile
Web04 | 2.8.151002.1 | Last Updated 22 Sep 2015
Article Copyright 2013 by Mike Barthold
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid