为什么在定义事件时我们需要"event"关键字?

tee*_*nup 102 .net c#

我不明白为什么在定义事件时我们需要"event"关键字,当我们可以在不使用"event"关键字的情况下执行相同的操作,只需使用委托.

例如

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

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

Jon*_*eet 134

类似于字段的事件和委托类型的公共字段看起来很相似,但实际上是非常不同的.

事件基本上类似于属性 - 它是一对添加/删除方法(而不是属性的get/set).当您声明类似字段的事件(即您没有自己指定添加/删除位的事件)时,会创建一个公共事件和一个私有支持字段.这允许您私下引发事件,但允许公共订阅.有了公共代表字段,任何人都可以删除其他人的事件处理程序,自己提升事件等等 - 这是一个封装灾难.

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

  • 这比MSDN官方的一行解释要好上千倍:'event关键字用于在发布者类中声明一个事件. (16认同)
  • @cowlinator“嗯……是的。这里的地板是用地板制成的。” (6认同)

Oak*_*Oak 34

event关键字有3种不同的东西:

  1. 您可以在界面中定义事件,即使您无法在界面中定义常规字段.
  2. 它将=()运算符(赋值和调用)的可见性更改为private,以便只有包含类可以调用事件或覆盖其中包含的所有方法.在-=+=运营商仍然可以在一个事件从类的外部定义它(他们让你旁边的事件写访问修饰符)调用.
  3. 您还可以覆盖事件的方式-=+=行为.

  • 您> MSDN。谢谢。 (2认同)

Eri*_*ert 24

其他答案都很好; 我想补充一些其他想法.

你的问题是"当我们有代表类型的字段时,为什么我们需要事件?" 我会扩展这个问题:如果你有委托类型的字段,为什么还需要方法,属性,事件,实例构造函数或终结器?为什么除了包含类型中的值和委托的字段之外还需要其他任何内容?为什么不说

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

不需要方法,属性或事件.我们为您提供这些内容,因为方法,属性和事件设计模式非常重要且有用,并且应该有一种标准的,有文档记录的,清晰的方式来实现它们.

  • 哇!它提醒我为什么喜欢c#!在我使用过的所有语言中,它在紧凑性,灵活性和可读语义之间取得了适当的平衡.唯一可比较的语言是Object Pascal. (3认同)
  • @ATL_DEV:这是有原因的。C# 语言的架构师 Anders Hejlsberg 之前是 Delphi 的架构师,Delphi 是一种基于 Object Pascal 的语言。 (3认同)

Mar*_*son 9

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

另一方面,您只能从定义它的类型中插入并调用'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(...);
   }       
}
Run Code Online (Sandbox Code Playgroud)

...但是这些代码只是(或多或少)完成了类似字段事件已经给我们带来的代码.