处理类中创建事件的最简单方法

时间:2016-07-09 00:04:52

标签: c# events

在VS 2015中玩游戏的时候,我正在创建一个属性并且在点击标签之前输入错误,它给了我一个非常简洁的创建事件的简单方法。我不确定如何使用它来接受其他参数来传递数据(因为我通常想要在提升事件时传递数据,其中包含正在进行的操作或已完成的操作)

它给出的代码如下:

public event EventHandler<EventArgs> MyEvent;
protected virtual void OnMyEvent(EventArgs e)
{
    EventHandler<EventArgs> handler = MyEvent;
    if (handler != null)
        handler(this, e);
}

乍一看,它与大多数示例类似,但是这种方法似乎不需要代表进行操作。与How to call an event manually in C#?

中的以下示例进行比较
public delegate void MyEventHandler(object sender, MyEventArgs e)
public event MyEventHandler MyEvent;
public void RaisesMyEvent()
{
   if(MyEvent != null) //required in C# to ensure a handler is attached
      MyEvent(this, new MyEventArgs(/*any info you want handlers to have*/));
}

我想知道的是,考虑到更优雅(干净)的代码,微软提供的方法(这个问题中的第一种方法)更好(看起来更干净),如果是这样,我怎么能调整它稍微接受除标准事件args之外的字符串和/或扩展eventargs以传递信息?

3 个答案:

答案 0 :(得分:1)

Visual Studio自动为您生成的代码实际上对于一个小条件更好:

public void RaisesMyEvent()
{
    if(MyEvent != null) //required in C# to ensure a handler is attached
        // Now if someone in another thread sets MyEvent to null the next line will still execute
        MyEvent(this, new MyEventArgs(/*any info you want handlers to have*/));
        // And throw a NullReferenceException
}

此代码具有竞争条件。它是相当罕见的,但它是可能的。 Visual Studio样板代码通过在调用事件处理程序之前制作事件处理程序的本地副本来避免此竞争条件。

至于如何将更多参数传递给事件处理程序:

有多种方式,但&#39;标准&#39;方法是创建一个扩展EventArgs的类。例如,PaintEventArgs扩展EventArgs并为Graphics处理程序添加RectangleOnPaint属性。

我通过创建基于MyEventArgs的{​​{1}}类来添加该基本模式,并添加您的方法需要使用的属性。

答案 1 :(得分:1)

要在EventHandler上传递自定义参数,您可以创建自己的派生自EventArgs的类,并更改声明,如下所示:

public event EventHandler<MyCustomEventArgs> MyEvent;

或者,如果您不喜欢处理程序中有object sender,则可以执行以下操作:

public event Action<MyCustomEventArgs> MyEvent;

甚至

public event Action<string> MyEvent;

就调用而言,微软更好。原因是您编写的空检查不是线程安全的。在执行空检查之前存储处理程序可确保您不调用null方法。

或者,使用C#6调用并利用空条件运算符:

MyEvent?.Invoke(whateverArgs);

答案 2 :(得分:1)

只需将EventArgs替换为您自己的班级:

class MyEventArgs : EventArgs
{
    public string Text { get; private set; }

    public MyEventArgs(string text)
    {
        Text = text;
    }
}

EventHandler<T>通用委托类型将接受EventArgsEventArgs的任何子类。

然后,当您致电OnMyEvent()时,只需传递您要通过该活动传递的数据的实例。

我同意有关线程安全调用的其他说明。这并不总是必需的,但它很容易实现,IDE提供的版本是安全的,而你的版本则不安全。

相关问题