.NET是否有内置的EventArgs <T>?

Dav*_*man 81 c# generics eventargs

我正准备为带有单个参数的事件args创建一个通用的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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

在我这样做之前,C#是否具有内置于该语言的相同功能?我似乎记得在C#2.0发布时遇到类似的东西,但现在我找不到它.

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

Ree*_*sey 63

不,您可能正在考虑EventHandler<T>,它允许您为任何特定类型的EventArgs定义委托.

不过,我个人认为这EventArgs<T>不太合适.在我看来,在事件args中用作"有效负载"的信息应该是一个自定义类,以使其使用和预期属性非常清晰.使用泛型类将阻止您将有意义的名称放置到位.("数据"代表什么?)

  • 在以数据为中心的类似MPI的应用程序中,通常会看到EventArgs <T>用于数据处理,以便开发人员可以利用内置的,类型安全的订阅/注册系统(.NET Events and Delegates),因为创建EventArgs子类只是为了传输数据是完全没有意义的.如果您的意图是传输数据,可以说定义EventArgs <T>更有意义,您可以为离散使用子类化而不考虑传输的数据.TL:DR这个答案的第一部分是事实和准确的,第二部分是主观/意见. (47认同)
  • ** EventHandler &lt;Customer&gt; **或** EventHandler &lt;Order&gt; **如何传达比** CustomerEventHandler **或** OrderEventHandler **更少的信息? (4认同)

NSG*_*aga 31

我必须说我不明白这里的所有'纯粹主义者'.即如果你已经定义了一个包类 - 它具有所有的细节,属性等 - 为什么hack创建一个额外的不必要的类只是为了能够遵循事件/ args机制,签名样式?事情是 - 不是.NET中的所有内容 - 或者说是"错过" - 这是"好" - MS多年来一直在"纠正"自己......我只想去创造一个 - 就像我做的那样 - 因为我就像那样需要它 - 并节省了我很多时间,

  • 并不意味着标记任何人:)点在事件中的'通用' - 如果你只需要十几个不同的事件,好吧.但如果您事先不知道T的性质 - 这只是在运行时才知道 - 那么,您需要一个通用事件.所以,如果你有一个应用程序是一个很好的部分处理w /泛型,任意类型的类型,未知 - 那么你还需要通用事件.或者说,对于每个问题都没有明确的解决方案,经验法则只是一个经验法则 - 这就是我所说的纯粹主义者,每个解决方案都不同,你需要权衡事物,利弊 (9认同)
  • 在这种情况下,"纯粹主义者"的观点是尽可能明确意图.在生产应用程序中,我有几十个这样的EventArgs类.一年后,如果我按照Reed的建议并创建一个自定义的EventArgs类,将会更容易理解我的所作所为. (3认同)
  • 设计不是黑白的,所以我倾向于在这里同意NSGaga。有时,“快而脏”是合适的。该语言应具有丰富的功能,以适合大多数用例。开发人员应自行决定合适的方法。MS上一次试图通过限制语言来强制“好的”设计是WPF,当时他们试图通过严重限制.NET API来强制使用XAML,这很糟糕。 (2认同)

Ulf*_*edt 9

它确实存在.至少,它现在确实如此.

您可以DataEventArgs<TData>在一些不同的Microsoft程序集/命名空间中找到它们,例如Microsoft.Practices.Prism.Events.但是,这些是您可能不会自然地包含在项目中的名称空间,因此您可能只使用自己的实现.


Jul*_*bre 7

如果您选择不使用Prism,但仍想尝试通用的EventArgs方法.

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

    public GenericEventArgs(T EventData)
    {
        this.EventData = EventData;
    }
}
Run Code Online (Sandbox Code Playgroud)

//使用以下示例代码声明ObjAdded事件

public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;
Run Code Online (Sandbox Code Playgroud)

//使用以下示例代码引发ObjAdded事件

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

//最后你可以订阅你的ObjAdded活动

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


epo*_*pox 5

没有内置的通用参数。如果您遵循 Microsoft EventHandler 模式,那么您可以像您建议的那样实现派生的 EventArgs: public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }

但是 - 如果您的团队风格指南接受简化 - 您的项目可以使用轻量级事件,如下所示:

public event Action<object, string> MyStringChanged;
Run Code Online (Sandbox Code Playgroud)

用法 :

// 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);
Run Code Online (Sandbox Code Playgroud)

通常 PoC 项目使用后一种方法。然而,在专业应用程序中,请注意外汇警察的理由#CA1009:https://msdn.microsoft.com/en-us/library/ms182133.aspx