【问题标题】:Does the ternary "?: operator" have a bug in C#?三元“?:运算符”在C#中是否有错误?
【发布时间】:2012-06-02 19:21:13
【问题描述】:

为什么我不能运行下面的代码?

    static int num = 0;
    static void Main(string[] args)
    {
        (num == 0) ? inc() : dec();
    }
    public static void inc()
    {
        num++; 
    }
    public static void dec()
    {
        num--;
    }

为什么 C# 不允许我使用三元 "?:" 运算符来检查条件,然后相应地运行方法而不需要返回任何值?相当于这个:

            if (num == 0) inc();
            else dec();

我不确定相同的规则是否适用于其他语言,例如 Java、C++ 等...

【问题讨论】:

    标签: c# conditional-operator


    【解决方案1】:

    为什么我不能运行下面的代码?

    因为您试图违反语言规范。条件运算符(C# 4 规范中的第 7.14 节)的操作数必须是 expressions - 并且调用返回类型为 void 的方法明确地“仅在语句表达式”(参见 C# 4 规范的第 7.1 节)。

    条件运算符的目的是提供一个表达式,该表达式是基于条件计算两个表达式之一的结果。 不是根据条件执行两个动作之一。只需使用if 语句即可。

    同样,条件运算符本身也不会形成有效的语句,就像其他各种运算符一样:

    a + b; // Invalid
    x = a + b; // Valid, assignment expression can be an expression-statement
    

    明确来自规范的第 8.6 节:

    并非所有表达式都允许作为语句。特别是,诸如 x + yx == 1 之类的仅计算值(将被丢弃)的表达式不允许作为语句。

    【讨论】:

    • @imad:我现在没有时间回答 - 但我建议你掌握 C# 4 语言规范并在那里阅读 :)
    【解决方案2】:

    Jon Skeet 的回答完美地证明了 C# 故意走与 C++ 不同的路线。很难说为什么,但我会尝试,因为我相信这个问题也值得回答。

    C# 与 C++ 和 Java 共享许多语法。在这种情况下,选择了 Java 方式。这涉及到无法将2 + 2; 作为独立语句编写,以及要求三元运算符返回值。

    我相信这两个决定都与消除无法访问的代码有很大关系。 2 + 2 中的 + 运算符可以被优化掉,因此如果它在代码中用于任何目的,那么该目的是不可靠的!静态分析(编译错误或警告)理想情况下应该告诉您在这种情况下似乎存在语义问题,并迫使您删除或重写无法访问的代码。

    因此,表达式不再总是语句,需要为 Java/C# 重新定义 C 语法,表达式总是返回值,语句从不返回值。

    现在?:if-else 的区别主要在于一个是表达式,一个是语句,至少在它们的典型用途上是这样。所以重新定义的语法干脆选择禁止 void 三元组,并为此推荐if-else

    【讨论】:

      【解决方案3】:

      因为三元运算符根据布尔表达式赋值。它的基本 C# 规范。如果您的方法是 void 返回类型,那么最好使用 if - else 或 switch case。

      int a = true ? 0 : 1; //Always works
      
      true ? 0 : 1; //This will never work.
      

      或者你的例子稍作修改。

      static int num = 0;
      
      static void Main(string[] args)
      {
          num = (num == 0) ? inc(num) : dec(num);
      }
      
      public static int inc(int lnum)
      {
          return lnum + 1;
      }
      
      public static int dec(int lnum)
      {
          return lnum - 1;
      }
      

      【讨论】:

        【解决方案4】:

        条件运算符 (?:) 根据布尔表达式的值返回两个值之一。

        它的行为方式与您在问题中描述的方式不同。 这里有更多关于三元运算符的字节

        http://msdn.microsoft.com/en-us/library/ty67wk28%28v=vs.80%29.aspx

        【讨论】:

          【解决方案5】:

          但是这样使用会起作用:

          static int num = 0;
          static void Main(string[] args)
          {
              num = (num == 0) ? inc(num) : dec(num);
          }
          public static int inc(int number)
          {
              return number + 1;
          }
          public static int dec(int number)
          {
              return number - 1;
          }
          

          【讨论】:

          • 上面的代码还是报错,可能是你忘了把void改成int
          • 是的,这会起作用。为什么?首先方法不是 void 而是返回值,其次是三元运算符分配回 num。
          猜你喜欢
          • 2012-08-08
          • 2022-01-24
          • 2021-10-06
          • 2014-12-14
          • 1970-01-01
          • 2012-02-06
          • 2019-10-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多