[英]What is the relationship between delegates and events?
Delegate
执行与函数指针相同的工作。 它可以被视为托管世界的函数指针。 它只是表示要调用的函数的地址,以及要调用其方法的特定对象。
我多次读到“ Delegate
”一词和“ Event
”一词,但我看不出它们之间的关系。 Event
是特定类型的代表吗?
简答:看看我关于这个主题的文章 。 更长的回答:
事件是代表之上的模式。 它们是发布者/订阅者模式(也称为观察者模式 )的实现,使用委托作为表示订阅的手段。
每当你看到类似的东西:
public event EventHandler Foo;
你应该考虑两种方法:
public void AddFooHandler(EventHandler handler) { ... }
public void RemoveFooHandler(EventHandler handler) { ... }
来自外部的客户可以做的就是订阅和取消订阅。 尤其是,客户端无法提高(被提供用于该目的,而不需要单独的方法)的情况下本身也不能“替换”或移除其他订阅。
到目前为止,答案都非常好,但他们都探索了这种关系的“机械”方面。 我看一下有点不同。
想想微波炉上的“开始”按钮。 该按钮为微波炉的用户提供抽象,按钮具有某些属性。 它有大小,有位置,有文字,按下时有动作。
C#程序中的Button
类也提供抽象,它同样具有某些属性。 与微波按钮一样,它具有大小和位置以及文本和按下时的动作。
大小和位置由整数表示,文本由字符串表示。 人们不会说微波炉按钮它“具有表示其大小和位置的整数以及表示其文本的字符串”。 对于软件按钮,它具有大小和位置以及文本的事实是按钮的语义 。 大小和位置以及文本由整数和字符串表示的事实是关于按钮构建的机制的事实,而不是关于按钮的目的或逻辑上它向世界呈现什么信息的事实。
软件按钮表示被点击作为事件的动作; 事件说“这是一个可以点击的东西”。 单击按钮时实际响应的代理集合是该机制的一部分。
一个属性告诉你关于一个类的事实。 它可能通过给你一个字符串来实现,但不要将字符串与属性混淆。 该字符串是该属性使用的事实传达给消费者的机制 。 事件还会告诉您有关课程的事实。 它通过委托来实现,因为委托是构建事件的机制 。
事件本质上是代理的容器,可以触发它们。 该事件还提供封装,允许事件的所有者成为触发注册代理的唯一来源。
简短的回答 。
通过使用委托来实现事件(这就是事件看起来像委托的原因)
答案很长
事件是由对象发送的消息,用于指示动作的发生。 该操作可能是由用户交互引起的,例如鼠标单击,或者可能由某些其他程序逻辑触发。 引发事件的对象称为事件发送者。 捕获事件并响应它的对象称为事件接收器。
在事件通信中,事件发送方类不知道哪个对象或方法将接收(处理)它引发的事件。 所需要的是源和接收器之间的中间(或类指针机制)。 .NET Framework定义了一个特殊类型(Delegate),它提供了函数指针的功能。
委托是一个可以保存对方法的引用的类。 与其他类不同,委托类具有签名,并且它只能保存对与其签名匹配的方法的引用。 因此委托等同于类型安全函数指针或回调。 虽然代表有其他用途,但此处的讨论主要关注代表的事件处理功能。 委托声明足以定义委托类。 声明提供委托的签名,公共语言运行库提供实现。 以下示例显示了事件委托声明。
更多信息:
http://msdn.microsoft.com/en-us/library/17sde2xt(v=vs.100).aspx
Delegate
是一个通常包含对象引用的类,它与指向方法的指针相结合,该方法是静态方法(在这种情况下,对象引用将为null
)或者保证对包含的对象类型起作用的方法在代表中。 调用委托将调用指示的方法,并在适当时将包含的对象传递给它。 委托也可以保存一个对象数组和一个关联方法数组,在这种情况下,调用委托将调用其相应对象上的每个方法,如果发生异常则中止该过程。 所有代理,即使只有一个对象/方法对的代理,都存储为从MulticastDelegate
派生的类型。
Event
是由对象公开的一对方法,其他代码可以使用它来请求对象在某些预期的未来情况下调用特定委托,或者通知对象它不再需要调用该委托。 大多数对象将接受传入的委托并将其添加到MulticastDelegate,然后在环境到达时调用该对象(调用MulticastDelegate将调用其所有成员),但对象可以自由地实现事件“add”和“删除“访问者,但他们认为合适。
一些额外的说明:
因为上面的第2点,经常使用术语“事件”,尤其是在C#中,以引用与事件关联的自动生成的委托字段。 但实际上,“事件”不是委托 - 它只是一对添加和删除方法(在VB中,“事件”也包含一种方法,仅用于类中,用于“提升” “一个事件(即调用先前已传递给”add“方法的委托);这只是语法糖,允许使用语法RaiseEvent EventName(params)
作为直接调用适当方法的替代方法)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.