当前位置:  开发笔记 > 编程语言 > 正文

如果事件在.NET中作为委托实现,那么.event IL部分的重点是什么?

如何解决《如果事件在.NET中作为委托实现,那么.eventIL部分的重点是什么?》经验,为你挑选了1个好方法。

我在Stack Overflow上看到了一些关于委托,事件和这两个特性的.NET实现的非常好的问题.特别是一个问题," C#Events如何在幕后工作? ",产生了一个很好的答案,很好地解释了一些微妙的观点.

上述问题的答案提出了这一点:

当您声明类似字段的事件时......编译器会生成方法和私有字段(与委托类型相同).在类中,当您引用ElementAddedEvent时,您指的是该字段.在课外,你指的是这个领域

从同一问题("类字段事件 ")链接的MSDN文章添加:

引发事件的概念恰好等同于调用事件所代表的委托 - 因此,没有用于引发事件的特殊语言结构.

为了进一步检查,我构建了一个测试项目,以便查看IL被编译为一个事件和一个委托:

public class TestClass
{
    public EventHandler handler;
    public event EventHandler FooEvent;

    public TestClass()
    { }
}

我希望委托字段handler和事件FooEvent编译成大致相同的IL代码,并使用一些其他方法来封装对编译器生成的FooEvent字段的访问.但是IL产生的不是我预期的:

.class public auto ansi beforefieldinit TestClass
    extends [mscorlib]System.Object
{
    .event [mscorlib]System.EventHandler FooEvent
    {
        .addon instance void TestClass::add_FooEvent(class [mscorlib]System.EventHandler)
        .removeon instance void TestClass::remove_FooEvent(class [mscorlib]System.EventHandler)
    }

    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        // Constructor IL hidden
    }

    .field private class [mscorlib]System.EventHandler FooEvent
    .field public class [mscorlib]System.EventHandler handler
}

由于事件只不过是使用编译器生成addremove方法的委托,因此我没想到会将事件视为IL中的事件.但是添加和删除方法是在一个开始的部分中定义的.event,而不是.method正常的方法.

我的最终问题是:如果事件只是作为具有访问方法的代表实现,那么拥有.eventIL部分有什么意义?如果不通过使用.method部分,它们不能在IL中实现吗?是.event相当于.method



1> Marc Gravell..:

我不确定这是否令人惊讶......与属性vs字段相比(因为属性与事件相同:通过访问器封装):

.field public string Foo // public field
.property instance string Bar // public property
{
    .get instance string MyType::get_Bar()
    .set instance void MyType::set_Bar(string)
}

此外 - 事件没有提到任何关于领域的事情; 他们定义访问者(添加/删除).代表支持者是一个实现细节; 事实上,类似字段的事件将字段声明为支持成员 - 就​​像auto-implemented-properties将字段声明为支持成员一样.其他实现是可能的(并且非常常见,尤其是在表单等中).

其他常见实现:

稀疏事件(控件等) - EventHandlerList(或类似):

// only one instance field no matter how many events;
// very useful if we expect most events to be unsubscribed
private EventHandlerList events = new EventHandlerList();
protected EventHandlerList Events {
    get { return events; } // usually lazy
}

// this code repeated per event
private static readonly object FooEvent = new object();
public event EventHandler Foo
{
    add { Events.AddHandler(FooEvent, value); }
    remove { Events.RemoveHandler(FooEvent, value); }
}
protected virtual void OnFoo()
{
    EventHandler handler = Events[FooEvent] as EventHandler;
    if (handler != null) handler(this, EventArgs.Empty);
}

(以上几乎是胜利形式事件的支柱)

Facade(虽然这会使"发件人"混淆一些;一些中间代码通常很有帮助):

private Bar wrappedObject; // via ctor
public event EventHandler SomeEvent
{
    add { wrappedObject.SomeOtherEvent += value; }
    remove { wrappedObject.SomeOtherEvent -= value; }
}

(以上也可用于有效地重命名事件)

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有