要了解差异,您可以查看这 2 个示例
带有委托的示例(在这种情况下,Action 是一种不返回值的委托)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
要使用委托,您应该这样做
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
此代码运行良好,但您可能有一些弱点。
例如,如果我写这个
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
在最后一行代码中,我重写了之前的行为,只是缺少了一个 +(我使用了 + 而不是 +=)
另一个弱点是每个使用 Animal 类的类都可以提升 RaiseEvent,只需调用它 animal.RaiseEvent()。
为了避免这个弱点,您可以在 c# 中使用events。
你的 Animal 类会以这种方式改变
public class ArgsSpecial :EventArgs
{
public ArgsSpecial (string val)
{
Operation=val;
}
public string Operation {get; set;}
}
public class Animal
{
public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it
public void RaiseEvent()
{
Run(this, new ArgsSpecial("Run faster"));
}
}
调用事件
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
区别:
- 您使用的不是公共属性,而是公共字段(编译器通过事件保护您的字段免受不必要的访问)
- 不能直接分配事件。在这种情况下,您无法执行我之前展示的覆盖行为的错误。
- 班外的任何人都不能提出该事件。
- 事件可以包含在接口声明中,而字段不能
注释
EventHandler 被声明为以下委托:
public delegate void EventHandler (object sender, EventArgs e)
它需要一个发送者(对象类型)和事件参数。如果来自静态方法,则 sender 为 null。
您也可以使用EventHAndler 代替这个使用EventHandler<ArgsSpecial> 的示例
请参阅here 以获取有关 EventHandler 的文档