为什么真假一元运算符需要成对声明?

时间:2014-12-18 16:05:19

标签: c# operator-overloading operators

根据 C#语言规范

  

truefalse一元运算符需要成对声明。如果类声明其中一个运算符而不声明另一个运算符,则会发生编译时错误。

这似乎是一个奇怪的选择,因为这两个操作员,尽管看起来有相关的名字,但却有不同的用途。

operator true的完整使用清单:

  1. 它允许在boolifwhiledo语句中使用该类型而不是for,并作为第一个三元? :运算符的操作数。 (仅当类型不具有匹配的隐式转换implicit operator bool时才相关。)
  2. 如果相同的struct / class以适当的方式重载operator |,它也允许使用短路运算符||
  3. operator false的{​​{3}}完整列表:

    • 如果相同的struct / class以适当的方式重载operator &,它也允许使用短路运算符&&

    请注意,如果operator false被相同类型重载,则operator & operator falseif等永远不会while相关。如果您想“否定”您的类型的实例,请改为重载一元operator !(“不是”)。

    因此,您需要operator true而非operator false似乎有合法用途,反之亦然。

    例如,如果我只需要使用上面的(1),我会重载operator true(以及可能operator !)。但我可能不想重载&,因此必须编写operator false毫无意义。

    在相反的方向上,我可以设计一种类型,我可以将&个实例放在一起,也可以使用短路&&,使用(•),所以我会重载operator false。但这并不一定意味着我希望我的类型有|||,更不用说我要求我的类型可以在ifwhile等内使用。

    无需重复|&“成对”。

    而不是实际限制,指定:

    会更有用
      

    (假设)如果类或结构超载operator false而没有operator &的匹配重载,则会发生编译时错误。

    事情的方式,人们被迫(通过C#规范)编写operator false成员,这些成员绝对没有被调用的机会。

    问题:要求operator trueoperator false一起去的动机或历史原因是什么?

1 个答案:

答案 0 :(得分:0)

这样做是为了迫使程序员为作业选择合适的工具。如果您认为自己超载operator false并且完全没有机会被调用,那么您可能应该重新转换转化operator bool(T)

运营商truefalse在很大程度上涵盖truefalse州重叠的情况,即对象可以是truefalse同时(或者,它既不是true也不是false)。

您描述的情况,即只有operator true(T)需要重载但没有匹配的operator false(T)的情况,由不同的机制 - 转换运算符bool涵盖。如果您只需要覆盖问题中的方案(1),则可以覆盖operator bool(T),并在需要bool的语句中使用您的类,而无需执行任何其他操作。

有一种特殊情况,您必须重载operator true和运算符false - 即,当您(1)重载operator &operator |时,以及(2)您希望在短路表达式中使用重载运算符。请注意,(1)和(2)都是必需的:当您不重载operator |operator &时,单个operator bool(T)就足以进行短路;在短路环境中不使用operator |operator &的情况也是如此。

在这种情况下,语言设计者有几种选择,其中没有一种看起来特别干净,因为在组合中使用时,某些正确的构造会成为错误。

  1. 检测到truefalse一起超载
  2. 检测到用于短路的&在没有false的情况下超载
  3. 检测到用于短路的|在没有true的情况下超载
  4. 检测到在短路环境中使用的true是否超载而没有匹配的&
  5. 检测到在短路环境中使用的false是否超载而没有匹配的|
  6. 关于错误2到5的最糟糕的部分是错误的一个组成部分来自使用您的类的代码,而不是来自类本身的代码。

    编译器设计人员选择实现选项1,2和3(除了2和3之外,他们需要重载truefalse以满足1)。他们可以选择选项4和5,但它不会使它更清洁,因为无论如何都需要检查三个不同的条件,其中一个是你无法控制的。

    最后,他们选择了对称性,隐含地假设如果你将truefalse重载用于短路&的上下文,你可能也会这么做支持|,反之亦然。