Chr*_*ris 5 .net c# events delegates cil
我在Stack Overflow上看到了一些关于委托,事件和这两个特性的.NET实现的非常好的问题.特别是一个问题," C#Events如何在幕后工作? ",产生了一个很好的答案,很好地解释了一些微妙的观点.
上述问题的答案提出了这一点:
当您声明类似字段的事件时......编译器会生成方法和私有字段(与委托类型相同).在类中,当您引用ElementAddedEvent时,您指的是该字段.在课外,你指的是这个领域
从同一问题("类字段事件 ")链接的MSDN文章添加:
引发事件的概念恰好等同于调用事件所代表的委托 - 因此,没有用于引发事件的特殊语言结构.
为了进一步检查,我构建了一个测试项目,以便查看IL被编译为一个事件和一个委托:
public class TestClass
{
public EventHandler handler;
public event EventHandler FooEvent;
public TestClass()
{ }
}
Run Code Online (Sandbox Code Playgroud)
我希望委托字段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
}
Run Code Online (Sandbox Code Playgroud)
由于事件只不过是使用编译器生成add
和remove
方法的委托,因此我没想到会将事件视为IL中的事件.但是添加和删除方法是在一个开始的部分中定义的.event
,而不是.method
正常的方法.
我的最终问题是:如果事件只是作为具有访问方法的代表实现,那么拥有.event
IL部分有什么意义?如果不通过使用.method
部分,它们不能在IL中实现吗?是.event
相当于.method
?
我不确定这是否令人惊讶......与属性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)
}
Run Code Online (Sandbox Code Playgroud)
此外 - 事件没有提到任何关于领域的事情; 他们只定义访问者(添加/删除).代表支持者是一个实现细节; 事实上,类似字段的事件将字段声明为支持成员 - 就像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);
}
Run Code Online (Sandbox Code Playgroud)
(以上几乎是胜利形式事件的支柱)
Facade(虽然这会使"发件人"混淆一些;一些中间代码通常很有帮助):
private Bar wrappedObject; // via ctor
public event EventHandler SomeEvent
{
add { wrappedObject.SomeOtherEvent += value; }
remove { wrappedObject.SomeOtherEvent -= value; }
}
Run Code Online (Sandbox Code Playgroud)
(以上也可用于有效地重命名事件)
归档时间: |
|
查看次数: |
2547 次 |
最近记录: |