Does .NET have a built-in EventArgs<T>?

C#GenericsEventargs

C# Problem Overview


I am getting ready to create a generic EventArgs class for event args that carry a single argument:

public class EventArg<T> : EventArgs
{
    // Property variable
    private readonly T p_EventData;
    
    // Constructor
    public EventArg(T data)
    {
        p_EventData = data;
    }
    
    // Property for EventArgs argument
    public T Data
    {
        get { return p_EventData; }
    }
}

Before I do that, does C# have the same feature built in to the language? I seem to recall coming across something like that when C# 2.0 came out, but now I can't find it.

Or to put it another way, do I have to create my own generic EventArgs class, or does C# provide one? Thanks for your help.

C# Solutions


Solution 1 - C#

No. You probably were thinking of EventHandler<T>, which allows you to define the delegate for any specific type of EventArgs.

I personally don't feel that EventArgs<T> is quite as good of a fit, though. The information used as a "payload" in the event args should be, in my opinion, a custom class to make its usage and expected properties very clear. Using a generic class will prevent you from being able to put meaningful names into place. (What does "Data" represent?)

Solution 2 - C#

I must say I don't understand all the 'purists' here. i.e. if you already have a bag class defined - which has all the specifics, properties etc. - why the hack create one extra unnecessary class just to be able to follow the event/args mechanism, signature style? thing is - not everything that is in .NET - or is 'missing from' for that matter - is 'good' - MS's been 'correcting' itself for years... I'd say just go and create one - like I did - cause I needed it just like that - and saved me lot of time,

Solution 3 - C#

It does exist. At least, it does now.

You can find DataEventArgs<TData> in some different Microsoft assemblies/namespaces, for instance Microsoft.Practices.Prism.Events. However these are namespaces that you might not find natural to include in your project so you might just use your own implementation.

Solution 4 - C#

In case you choose not to use Prism, but still would like to try a generic EventArgs approach.

public class GenericEventArgs<T> : EventArgs
{
    public T EventData { get; private set; }

    public GenericEventArgs(T EventData)
    {
        this.EventData = EventData;
    }
}

// Use the following sample code to declare ObjAdded event

public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;

// Use the following sample code to raise ObjAdded event

private void OnObjAdded(TargetObjType TargetObj)
{
    if (ObjAdded!= null)
    {
        ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj));
    }
}

// And finnaly you can subscribe your ObjAdded event

SubscriberObj.ObjAdded +=  (object sender, GenericEventArgs<TargetObjType> e) =>
{
    // Here you can explore your e.EventData properties
};

Solution 5 - C#

THERE IS NO BUILT-IN GENERIC ARGS. If you follow Microsoft EventHandler pattern, then you implement your derived EventArgs like you suggested: public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }.

HOWEVER - if your team style guide accepts a simplification - your project can use a lightweight events, like this:

public event Action<object, string> MyStringChanged;

usage :

// How to rise
private void OnMyStringChanged(string e)
{
    Action<object, string> handler = MyStringChanged;    // thread safeness
    if (handler != null)
    {
        handler(this, e);
    }
}

// How to handle
myObject.MyStringChanged += (sender, e) => Console.WriteLine(e);

Usually a PoC projects use the latter approach. In professional applicatons, however, be aware of FX cop justification #CA1009: https://msdn.microsoft.com/en-us/library/ms182133.aspx

Solution 6 - C#

The problem with a generic type is that even if DerivedType inherits from BaseType, EventArgs(DerivedType) would not inherit from EventArgs(BaseType). Using EventArgs(BaseType) would thus prevent later using a derived version of the type.

Solution 7 - C#

The reason this does not exist is because what would end up happening is you implement this, and then when you go to fill in the T you should create a class with strongly typed unambiguous properties that acts as the data bag for your event arg, but halfway through implementing that you realize there's no reason you don't just make that class inherit from EventArgs and call it good.

Unless you just want a string or something similarly basic for your data bag, in which case there are probably EventArgs classes standard in .NET which are meant to serve whatever simple purpose you're getting at.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDavid VeenemanView Question on Stackoverflow
Solution 1 - C#Reed CopseyView Answer on Stackoverflow
Solution 2 - C#NSGaga-mostly-inactiveView Answer on Stackoverflow
Solution 3 - C#Ulf ÅkerstedtView Answer on Stackoverflow
Solution 4 - C#Julio NobreView Answer on Stackoverflow
Solution 5 - C#epoxView Answer on Stackoverflow
Solution 6 - C#supercatView Answer on Stackoverflow
Solution 7 - C#Jimmy HoffaView Answer on Stackoverflow