为什么在定义事件时需要“事件”关键字?
我不明白为什么我们在定义事件的时候需要“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模式是重要和有用的,值得有一个标准的,文件化的,明确的方式来实现他们的语言。
事件关键字有三个不同的事情:
- 即使无法在接口中定义常规字段,也可以在接口中定义事件。
- 它将
=
和()
运算符(赋值和调用)的可见性更改为private,以便只有包含的类才能调用该事件或覆盖其中包含的所有方法。-=
和+=
运算符仍然可以在定义类的外部事件上调用(它们获得您在事件旁边编写的访问修饰符)。 - 你也可以重写
-=
和+=
行为。
这部分需要,因为如果你省略了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)做一些类似事件已经给我们的代码。
与委托领域相比,事件具有明显的优势。 事件可以在接口中定义,而不是字段,为代码添加抽象,更重要的是:事件只能从定义类中调用。 在你的情况下,任何人都可以调用这个事件,可能会破坏你的代码。
看到这个博客文章进一步的信息。
- StreamWriter.Flush()和StreamWriter.Close()有什么区别?
- Console.WriteLine()与Debug.WriteLine()之间有什么区别?
- 在C#中元帅“char *”
- 如何转换WebResponse.GetResponseStream返回string?
- Visual Studio 2010:无法parsingmscorlib目标框架“.NETFramework,版本= v4.0”
- CPU友好的无限循环
- 是否有可能完全用托pipe的.NET语言编写JIT编译器(本地代码)
- 什么是“索引超出范围”exception,我该如何解决?
- 存储库本身通常不被testing?