Eri*_*ert 47
其他答案基本上是正确的,但这是另一种看待它的方式:
我是那些混淆事件和委托实例的开发人员之一.在我看来,它们是一样的.
我想到了一个关于没有看到森林树木的古老谚语.我所做的区别是事件处于比委托实例字段更高的"语义级别".一个事件告诉消费者类型"你好,我是一个喜欢在发生事情时告诉你的类型".类型来源事件; 这是公共合同的一部分.
作为一个实现细节,该类选择如何跟踪谁有兴趣收听该事件,以及告诉订阅者该事件发生的内容和时间,是该类的业务.通常使用多播委托进行此操作,但这是一个实现细节.这是一个常见的实现细节,将两者混淆是合理的,但我们确实有两个不同的东西:公共表面和私有实现细节.
类似地,属性描述对象的语义:客户具有名称,因此Customer类具有Name属性.您可能会说"他们的名字"是客户的财产,但您永远不会说"他们的名字"是客户的一个领域 ; 这是特定类的实现细节,而不是关于业务语义的事实.通常将属性实现为字段是类机制的私有细节.
Ben*_*igt 41
属性也不是字段,尽管它们感觉像它们.它们实际上是一对具有特殊语法的方法(getter和setter).
事件类似于一对具有特殊语法的方法(订阅和取消订阅).
在这两种情况下,您通常在类中都有一个私有的"支持字段",它保存由getter/setter/subscribe/unsubscribe方法操纵的值.并且有一个自动实现的属性和事件语法,编译器为您生成支持字段和访问器方法.
目的也是相同的:属性提供对字段的受限访问,其中在存储新值之前运行某些验证逻辑.并且事件提供对委托字段的受限访问,其中消费者只能订阅或取消订阅,不能读取订阅者列表,也不能立即替换整个列表.
ang*_*son 24
让我们考虑一下声明事件的两种方法.
您可以使用显式add/ remove方法声明事件,也可以声明没有此类方法的事件.
换句话说,你声明这样的事件:
public event EventHandlerType EventName
{
add
{
// some code here
}
remove
{
// some code here
}
}
Run Code Online (Sandbox Code Playgroud)
或者你这样声明:
public event EventHandlerType EventName;
Run Code Online (Sandbox Code Playgroud)
问题是,在某些方面它们是相同的,在其他方面,它们是完全不同的.
从外部代码的角度来看,即发布事件的类之外的代码,它们完全相同.要订阅活动,请调用方法.要取消订阅,您可以使用其他方法.
不同之处在于,在上面的第二个示例代码中,这些方法将由编译器为您提供,但是,它仍然是如何.要订阅该事件,请调用方法.
但是,在C#中这样做的语法是相同的,你可以这样做:
objectInstance.EventName += ...;
Run Code Online (Sandbox Code Playgroud)
要么:
objectInstance.EventName -= ...;
Run Code Online (Sandbox Code Playgroud)
所以从"外部视角"来看,这两种方式完全没有区别.
但是,在课堂上,有一个区别.
如果您尝试访问类中的EventName标识符,那么实际上您指的field是支持该属性的标识符,但前提是您使用的语法未明确声明add/ remove方法.
典型的模式是这样的:
public event EventHandlerType EventName;
protected void OnEventName()
{
var evt = EventName;
if (evt != null)
evt(this, EventArgs.Empty);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当您提到时EventName,您实际上是指包含类型委托的字段EventHandlerType.
但是,如果你已经显式声明了add/ removemethods,那么引用类中的EventName标识符就像在类之外一样,因为编译器不能保证它知道存储订阅的字段或任何其他机制. .
事件是代理的访问者.就像一个属性是一个字段的访问者.使用完全相同的实用程序,它可以防止代码弄乱委托对象.就像属性具有get和set访问器一样,事件具有添加和删除访问器.
它的行为与属性有所不同,如果您不自己编写添加和删除访问器,则编译器会自动生成它们.包括存储委托对象的私有备份字段.类似于自动属性.
你不经常这样做,但肯定并不罕见..NET框架通常这样做,例如Winforms控件的事件存储在EventHandlerList中,添加/删除访问器通过其AddHandler()和RemoveHandler()方法操作该列表.优点是所有事件(有很多)只需要类中的一个字段.
| 归档时间: |
|
| 查看次数: |
3459 次 |
| 最近记录: |