NET 有内置的 EventArgs < T > 吗?

我准备为携带单个参数的事件参数创建一个通用的 EventArgs 类:

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; }
}
}

在此之前,C # 是否具有相同的语言内置特性?我似乎记得在 C # 2.0出来的时候遇到过类似的东西,但现在我找不到了。

或者换句话说,我必须创建自己的通用 EventArgs 类,还是 C # 提供一个?谢谢你的帮助。

40545 次浏览

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?)

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.

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.

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,

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.

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
};

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