【问题标题】:Why is an event not a first class object in C#为什么事件不是 C# 中的第一类对象
【发布时间】:2016-06-29 00:02:59
【问题描述】:

例如,我知道我不能将事件传递给方法或构造函数,但我不明白为什么不能。是什么让事件与代表集合不同?

【问题讨论】:

  • @cFrozenDeath 我确定我不明白什么是事件。如果我这样做了,我就不会问这个问题了。
  • 为了未来的读者,您能否添加一段演示此行为的 sn-p 代码?

标签: c#


【解决方案1】:

...虽然事件在您表达添加和删除操作的方式方面看起来像委托实例,但它们不是。

事件是成对的方法,在 IL 中适当地修饰以将它们联系在一起并让语言知道方法代表事件。这些方法对应于添加和删除操作,每个操作都采用相同类型(事件的类型)的委托实例参数。你对这些操作做什么几乎取决于你,但典型的用途是在事件的处理程序列表中添加或删除委托。

来自Jon SkeetC# in Depth: Delegates and Events

【讨论】:

  • 这只是说明事件不是一流的对象。问题问为什么他们不是,作为前提,假设他们不是。
  • @Servy 我认为知道事件是成对的方法可以在某种程度上解释为什么,不是吗?如果您想知道它们为什么会这样,那么我想说主要原因是封装。只能在声明事件的类中调用事件。通过拥有一个私有的委托成员和一对公共访问器方法,可以或多或少地模拟 c# 中的事件。 c# 中的事件符合这一点(而不是人们创建类似但不同的方法来解决这个问题)并添加一些语法糖,这样我们就可以少打字了。
  • 这就是为什么事件有尽可能多的支持。问题是它为什么会停在那里,以及为什么不能,例如,将事件作为参数传递给方法。鉴于事件已被封装,您绝对可以设计一种语言来做到这一点。你为什么不能更深入地支持事件的理由是支持它们可能是的情况(但甚至没有解决为什么不能)。
  • 我同意,我无法回答您所解释的问题。我以我解释的方式回答。您可能认为这是错误的,其他人也可能认为这是错误的,这当然是这里有投票系统的原因:)
  • 您错过了问题的关键部分:“是什么让一个事件与代表集合不同?”我认为答案涵盖得相当好,尽管我不能真正相信这一点。
【解决方案2】:

在一个类中声明一个事件,以允许该类外部的对象附加到该事件并在该类中发生更改时得到通知。

如果它是一等公民,那么事件可以从外部类调用,这意味着任何引用该事件的流氓代码,例如Button,都可能导致Click 要触发的事件。

为了防止这种事件有特殊的访问规则,只允许声明事件的类(并且甚至不允许它自己的子类)触发事件。

因此,为了安全起见,事件不是 .NET Framework 的一等公民。

【讨论】:

  • 虽然我认为@withakay 的答案在技术上是正确的答案,但我认为你的答案是一个更好的实际例子,说明了为什么你不能传递事件。
  • 这完全是错误的。您可以使事件成为一等公民,而不允许从类型外部调用它们。按照这种逻辑,私有字段不应该是一等公民,因为它不能在类之外访问,也不能在具有私有 setter 的属性或任何其他具有范围的东西(即基本上所有东西)之外访问。
  • @Servy - 我不同意。将事件与私有字段进行比较是非常不同的。您可以传递私有字段的值/引用并将其与 100% 的功能一起使用,但您不能在事件中这样做。
  • @Enigmativity 是的,您目前不能对事件执行此操作是正确的。问题是专门问为什么你不能。说你不能当然是这个问题的前提。你绝对可以允许它,并且安全地这样做,C# 根本不会这样做。
  • @Enigmativity 正如我特别解释的那样,这种解释是完全错误的。不能从外部类调用事件这一事实绝不会阻止语言创建构造以将事件作为封装对象传递,只要它保持外部对象不能触发它(这是微不足道的去做)。这就像声称方法不能是一等公民,因为私有方法不能从定义它们的类的外部显式调用。鉴于方法一等公民,显然这不是问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-31
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
相关资源
最近更新 更多