【问题标题】:Best practice in declaring events in C#在 C# 中声明事件的最佳实践
【发布时间】:2013-05-28 12:50:07
【问题描述】:

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

捷径:

  public event EventHandler MyEvent;

漫长的路:

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

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

【问题讨论】:

  • 为什么自动属性是不好的做法?
  • 也许是因为我很懒,但我总是选择短版:)
  • 我的第一个猜测是,对于大多数情况来说,短途已经绰绰有余了。当你真正需要它时,需要很长的路要走,即。无论是否注册事件,您都需要做一些额外的事情。
  • @Lews :我不是指汽车属性,而是公共成员。例如:public int Number; 是不好的做法。 public int Number { get; set; } 不是。
  • 有时也需要实际的委托来进行调试、清除调用列表等。

标签: c# events event-handling


【解决方案1】:

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

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

但是:无论哪种方式,这都是封装的(在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 操作(CompareExchange 等)来实现这一点,因此它不需要专用的私有同步对象。

【讨论】:

    【解决方案2】:

    第一种方法在下面与创建名称为MyEvent 的私有EventHandler 完全相同。当它在类中被访问时,事件处理程序被返回(即调用委托没有问题),当它在类之外被调用时(myClassInstance.MyEvent += SomeHandler/myClassInstance.MyEvent -= SomeHandlerAdd/Remove 方法被分别调用。而且这些方法和你用第二种方法写的方法是一样的(除了它们增加了线程安全)。

    那你为什么要在你实际上不需要的时候写更多的代码呢?

    【讨论】:

    • 实际上,它们并不完全相同;编译器包括类字段事件示例(第一个)的线程安全
    【解决方案3】:

    为了检查 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);
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-26
      • 1970-01-01
      • 1970-01-01
      • 2018-07-19
      • 1970-01-01
      相关资源
      最近更新 更多