为什么在定义事件时需要“事件”关键字?

我不明白为什么我们在定义事件的时候需要“event”关键字,什么时候我们可以在不使用“event”关键字的情况下做同样的事情,只需要使用委托。

例如

public delegate void CustomEventHandler(int a, string b); public event CustomEventHandler customEvent; customEvent += new CustomEventHandler(customEventHandler); customEvent(1,"a"); // Raising the event 

在这里,如果我从第二行删除“event”关键字,那么我也可以通过调用委托来引发事件。 任何人都可以告诉我为什么这个事件的关键字需要?

委托types的字段事件和公共字段看起来相似,但实际上是非常不同的。

事件基本上就像一个属性 – 这是一对添加/删除方法(而不是一个属性的get / set)。 当你声明一个类似字段的事件(也就是你自己没有指定添加/删除位的事件)时,会创build一个公共事件,并创build一个专用的后台字段。 这可以让你私下提出事件,但允许公开订阅。 使用公共代理字段, 任何人都可以删除其他人的事件处理程序,自己提出事件等 – 这是一个封装的灾难。

有关事件(和代表)的更多信息,请阅读我关于此主题的文章 。 (在某些时候,我需要更新这个C#4,它稍微改变了类似于事件的事件,但它的要点仍然是正确的。)

其他答案是好的; 我只想添加其他的东西来思考。

你的问题是“当我们有委托types的字段时,为什么我们需要事件? 我会延长这个问题:如果你有委托types的字段,为什么你需要方法,属性,事件,实例构造函数或终结器? 为什么除了包含值和代表types的字段以外,还需要其他任何东西 ? 为什么不说呢

 class C { private int z; public readonly Func<int, int> M = (int x)=>{ return x+z; } // ... and so on } 

不需要方法,属性或事件。 我们给你的东西,因为方法,财产和事件devise模式是重要和有用的,值得有一个标准的,文件化的,明确的方式来实现他们的语言。

事件关键字有三个不同的事情:

  1. 即使无法在接口中定义常规字段,也可以在接口中定义事件。
  2. 它将=()运算符(赋值和调用)的可见性更改为private,以便只有包含的类才能调用该事件或覆盖其中包含的所有方法。 -=+=运算符仍然可以在定义类的外部事件上调用(它们获得您在事件旁边编写的访问修饰符)。
  3. 你也可以重写-=+=行为。

这部分需要,因为如果你省略了event关键字,它就会破坏封装。 如果它只是一个公共多播委托,任何人都可以调用它,将其设置为null或篡改它。 如果存在一个名为MailNotifier的类,并且它有一个名为MailReceived的事件,那么其他types通过调用mailNotifier.MailReceived()可以触发该事件是没有意义的。

另一方面,你只能干涉和调用定义它的types的'field like'事件。

如果你想保持你的事件调用私人,没有什么可以阻止你做这样的事情:

 public class MyClassWithNonFieldLikeEvent { private CustomEventHandler m_delegate; public void Subscribe(CustomEventHandler handler) { m_delegate += handler; } public void Unsubscribe(CustomEventHandler handler) { m_delegate -= handler; } private void DoSomethingThatRaisesEvent() { m_delegate.Invoke(...); } } 

…但是这只是(或多或less)做一些类似事件已经给我们的代码。

与委托领域相比,事件具有明显的优势。 事件可以在接口中定义,而不是字段,为代码添加抽象,更重要的是:事件只能从定义类中调用。 在你的情况下,任何人都可以调用这个事件,可能会破坏你的代码。

看到这个博客文章进一步的信息。