且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何C#事件的幕后工作?

更新时间:2022-01-11 01:50:30

我在的的文章,但这里的总结,假设你是相当满意代表自己:

I've written this up in a fair amount of detail in an article, but here's the summary, assuming you're reasonably happy with delegates themselves:

  • 的事件仅仅是一个增加的方法和删除的方法,以同样的方式,一个属性是实际上只是一个获取方法和集的方法。 (事实上​​,CLI允许一个升/火的方法为好,但C#从来没有产生这个。)元数据描述了事件引用的方法。
  • 在声明的 现场般的事件 的(如您ElementAddedEvent)编译器生成的方法的和(同类型的代表)的私人领域的。在类中,当您参考ElementAddedEvent你指到外地。在类外,你指到外地。
  • 当有人赞同事件(与+ =运算符)调用add方法。当他们取消(使用 - =运算符)调用删除
  • 有关字段的事件,有一些同步,但否则添加/删除只需调用委托。的联合 / 删除更改值自动生成的场。这两个操作都分配给支持字段 - 记住,代表是不可改变的。换句话说,自动生成的code是非常喜欢这样的:

  • An event is just an "add" method and a "remove" method, in the same way that a property is really just a "get" method and a "set" method. (In fact, the CLI allows a "raise/fire" method as well, but C# never generates this.) Metadata describes the event with references to the methods.
  • When you declare a field-like event (like your ElementAddedEvent) the compiler generates the methods and a private field (of the same type as the delegate). Within the class, when you refer to ElementAddedEvent you're referring to the field. Outside the class, you're referring to the field.
  • When anyone subscribes to an event (with the += operator) that calls the add method. When they unsubscribe (with the -= operator) that calls the remove.
  • For field-like events, there's some synchronization but otherwise the add/remove just call Delegate.Combine/Remove to change the value of the auto-generated field. Both of these operations assign to the backing field - remember that delegates are immutable. In other words, the autogenerated code is very much like this:

// Backing field
// The underscores just make it simpler to see what's going on here.
// In the rest of your source code for this class, if you refer to
// ElementAddedEvent, you're really referring to this field.
private EventHandler<EventArgs> __ElementAddedEvent;


// Actual event
public EventHandler<EventArgs> ElementAddedEvent
{
    add
    {
        lock(this)
        {
            // Equivalent to __ElementAddedEvent += value;
            __ElementAddedEvent = Delegate.Combine(__ElementAddedEvent, value);
        }
    }
    remove
    {
        lock(this)
        {
            // Equivalent to __ElementAddedEvent -= value;
            __ElementAddedEvent = Delegate.Remove(__ElementAddedEvent, value);
        }
    }
}

  • 产生磁场中的情况下,初始值为 - 它总是会成为再次,如果所有用户都去掉了,因为这是Delegate.Remove的行为。

  • The initial value of the generated field in your case is null - and it will always become null again if all subscribers are removed, as that is the behaviour of Delegate.Remove.

    如果你想要一个无操作处理程序来订阅你的事件,从而避免无效检查,你可以这样做:

    If you want a "no-op" handler to subscribe to your event, so as to avoid the nullity check, you can do:

    public EventHandler<EventArgs> ElementAddedEvent = delegate {};
    

    委托{} 只是不关心它的参数,并进行匿名方法罢了。

    The delegate {} is just an anonymous method which doesn't care about its parameters and does nothing.

    如果有什么,目前还不清楚,请你和我会尽力帮助!

    If there's anything that's still unclear, please ask and I'll try to help!