13

我知道以下两种方法有效,但我想知道在性能/维护/其他方面是否更好。

捷径:

  public event EventHandler MyEvent;

漫长的道路:

  private EventHandler _myEvent;
  public event EventHandler MyEvent
  {
     add { _myEvent += value; }
     remove { _myEvent -= value; }
  }

很长的路似乎类似于用属性封装成员,这确实是一个很好的做法。但这适用于事件处理程序吗?

4

3 回答 3

30

在这种情况下,“良好做法”的论点就有点花招了;第一个是“类场事件”;你注意:

很长的路似乎类似于用属性封装成员,

但是:无论哪种方式,它都被封装(在add/后面remove);因此,与属性相比,这确实是以下之间的区别:

public int Foo {get;set;}

private int foo;
public int Foo {
    get { return foo; }
    set { foo = value; }
}

在这种情况下,我会说“使用第一个,除非你有实际理由不这样做”——它仍然隐藏在访问器后面。此外,重要的是要注意,您的第二个示例不是类似字段的事件(第一个示例)扩展为:编译器将线程安全性添加到混合中。所以:我会说使用第一个样本:

public event EventHandler MyEvent;

请注意,线程安全的“方式”取决于您使用的编译器版本(实际上是哪个规范)。在最近的 Microsoft C# 编译器中,它通过Interlocked操作 ( CompareExchangeetc) 执行此操作,因此它不需要专用的私有同步对象。

于 2013-05-28T12:54:32.130 回答
5

EventHandler第一种方法在下面与创建私有名称完全相同MyEventmyClassInstance.MyEvent += SomeHandler当在类( / myClassInstance.MyEvent -= SomeHandler)之外调用它时,将返回类事件处理程序(即调用委托没有问题) Add/Remove分别调用方法。这些方法与您以第二种方式编写的方法相同(除了它们增加了线程安全性)。

那么,当您实际上不需要代码时,为什么还要编写更多代码呢?

于 2013-05-28T12:53:10.063 回答
1

为了检查 Marc Gravel 的意思,我尝试了以下代码:

public event EventHandler MyEventShortWay;

private EventHandler _myEvent;
public event EventHandler MyEventLongWay
{
    add { _myEvent += value; }
    remove { _myEvent -= value; }
}

我对生成的内容感到惊讶(我编辑了反编译的变量名):

private EventHandler _myEventShortWay;

public event EventHandler MyEventShortWay
    {
        add
        {
            EventHandler handler2;
            EventHandler myEventShortWay = this._myEventShortWay;
            do
            {
                handler2 = myEventShortWay;
                EventHandler handler3 = (EventHandler)Delegate.Combine(handler2, value);
                myEventShortWay = Interlocked.CompareExchange<EventHandler>(ref this._myEventShortWay, handler3, handler2);
            }
            while (myEventShortWay != handler2);
        }
        remove
        {
            EventHandler handler2;
            EventHandler myEventShortWay = this._myEventShortWay;
            do
            {
                handler2 = myEventShortWay;
                EventHandler handler3 = (EventHandler)Delegate.Remove(handler2, value);
                myEventShortWay = Interlocked.CompareExchange<EventHandler>(ref this._myEventShortWay, handler3, handler2);
            }
            while (myEventShortWay != handler2);
        }
    }

    private EventHandler _myEvent;

    public event EventHandler MyEventLongWay
    {
        add
        {
            this._myEvent = (EventHandler) Delegate.Combine(this._myEvent, value);
        }
        remove
        {
            this._myEvent = (EventHandler)Delegate.Remove(this._myEvent, value);
        }

    }
于 2013-05-28T13:54:59.507 回答