我在 Stack Overflow 上看到了一些关于委托、事件和这两个功能的 .NET 实现的非常好的问题。特别是一个问题,“ C# 事件如何在幕后工作? ”,产生了一个很好的答案,很好地解释了一些微妙的观点。
上述问题的答案说明了这一点:
当您声明类似字段的事件时......编译器会生成方法和私有字段(与委托的类型相同)。在类中,当您引用 ElementAddedEvent 时,您指的是该字段。在课堂之外,您指的是该领域
从同一问题(“ Field-like events ”)链接的 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
}
由于事件只不过是编译器生成的委托add
和remove
方法,我没想到会在 IL 中看到事件被视为更多。但是 add 和 remove 方法是在开头的部分中定义的.event
,而不是.method
像普通方法那样。
我的终极问题是:如果事件被简单地实现为具有访问器方法的委托,那么拥有.event
IL 部分的意义何在?如果没有这个,它们不能通过使用.method
部分在 IL 中实现吗?.event
相当于.method
? _