代码之家  ›  专栏  ›  技术社区  ›  Ed Guiness

布尔表达式,为什么只有两个词?

  •  4
  • Ed Guiness  · 技术社区  · 16 年前

    既然写是有效的

    a = b = c = 2;
    

    它也会很好,而不是

    bool allTwo = a == 2 && b == 2 && c == 2;
    

    改为写

    bool allTwo = a == b == c == 2;
    

    但我不能,因为a==b的计算结果是一个布尔值,而这个布尔值再也不能与整数进行比较。

    有没有一个语言设计的原因,它是这样实现的?

    8 回复  |  直到 16 年前
        1
  •  8
  •   Pete Kirkham    16 年前

    表达式的类型 a == b 是布尔型的,因此您要么必须打破一个规则,即表达式在上下文中表示相同的内容,要么使用n元==运算符,以便 a == b == c 被解析为 (== a b c) 而不是 (== (== a b) c) . 这意味着你需要 (a == b) == c 将布尔值C与 (a == b) 这是可以的,但不是C传统的简单的C语法风格。

        2
  •  5
  •   Bob    16 年前

    好吧,表达 c == 2 会回来 true 所以 b 会被比作 而不是2。

    编辑:它很可能是以这种方式实现的,因为这就是C样式语言处理布尔表达式的方式。他们必须对多个术语进行特殊的异常处理,并以不同的方式实现它,而使用赋值运算符则更简单:最右边的表达式计算的值在逻辑上可以应用于链中的下一个表达式。似乎设计师们采取了简单的方法。

        3
  •  3
  •   Dr. Wily's Apprentice    16 年前

    从我的角度来看,这是一个清晰的问题。如果由我来决定,我会考虑如何添加这样一个语言特性,可能会对计算复杂表达式的方式增加太多的歧义。在某些情况下,a==b==c与(a==b)==c不同吗?如果我真的想将C与a==b的布尔结果进行比较,而不是将c与b进行比较呢?在大多数情况下,编译器可能会找到适当的比较,但是如果C隐式地转换为bool,尽管不太可能,那么可能无法判断。

    所以就我个人而言,我不确定这是否值得麻烦。虽然它在语法上看起来不太好,但您可以构建自己的实用函数来比较多个对象的相等性,如:

        public static bool Equals(this object x, params object[] y)
        {
            for (int i = 0; i < y.Length; i++)
            {
                if (!object.Equals(x, y[i]))
                    return false;
            }
            return true;
        }
    

    然后你可以这样使用它:

            if (a.Equals(b, c, d, e, f, g))
            {
                // ...
            }
    
        4
  •  2
  •   Community Mohan Dere    9 年前

    我找不到引用,但我想是埃里克·利珀特(?)谁说得最好:不实现特性是免费的。也见 http://blog.ryjones.org/2005/07/12/product-development/ http://blog.ryjones.org/2005/07/12/product-development/产品开发/

    它们有许多要实现的特性,我不能想象像这样的非标准的、有问题的价值会是一个高优先级。我不是说它不值钱,但它可能会导致混乱,可能不会经常使用,等等。我认为A1ex07也有一个很好的观点。这必须是一个自定义案例,因为它不能再被一般性地处理了(=总是返回布尔值,等等)。

    现在您可以对Linq执行相同的操作,但语法要复杂一些,需要分配某种类型的数组:

    bool allTwo = new int[] { a, b, c }.All(i => i == 2);
    

    你可以倒着做,看看有没有!= 2:

    bool allNotTwo = new int[] { a, b, c }.Any(i => i != 2);
    

    在这两种情况下,一旦其中一个无效,它也会立即退出,因此您通常不会浏览整个列表。

    编辑: 还有一点: Does C# have too many language features?

    新的事物 非常 有益于 把它变成语言

        5
  •  1
  •   a1ex07    16 年前

    做你想做的事, operator == 应返回对象。在这种情况下,我们还有另一个问题——现在我们需要将任何对象隐式转换为布尔值。这样的转换也会产生额外的问题。

        6
  •  1
  •   Jonathan Lonowski    16 年前

    我认为你的问题在你的参考点上有些恶化。

    没有什么神奇的 a = b = c = 2 建议 a == b == c == 2 应该像你想要的那样工作——事实上,恰恰相反。

    赋值运算符仅为2个操作数定义,并返回正在设置的值。它们的字符串只是将值从每个运算符传递到下一个运算符:

    1: a = (b = (c = 2));
    2: a = (b = (2));
    3: a = (2);
    

    所以,这同样适用于 A==B==C==2 :

    1: bool allTwo = (a == (b == (c == 2)));
    2: bool allTwo = (a == (b == ([Boolean])));
    3: bool allTwo = (a == ([Boolean]));
    4: bool allTwo = ([Boolean]);
    

    所以,技术原因就是 C# 不包含对字符串运算符进行特殊处理的定义。

    至于语言设计和实现,原因很可能是为了防止歧义和额外的复杂性。尽管你可能想要 A==B==C==2 定义为 所有平等 现在,在下一行,您可能非常需要它作为当前实现。如何区分行为?这真的值得我们努力去实现吗?

    或是 a == 2 && b == 2 真的那么糟糕?;)

        7
  •  1
  •   Powerlord    16 年前

    忽略返回值,它还与 operator associativity .

    赋值运算符是右关联的。也就是说,首先计算赋值运算符的右侧。这就是你能做到的原因 a = b = c = 2 让他们都分配值2。否则,你会以 a 具有旧的价值 b 具有旧的价值 c .

    大多数其他运算符都是左相关的,尤其是短路逻辑运算符( && || )也就是说 a == b a && b 评价 第一。

    你可以这么说 == 可能是右联想…除了在.NET中不能,因为对于对象, A=B 转换为(除非重写) a.Equals(b) (或者) a.ReferenceEquals(b) …我不记得了)。

        8
  •  -1
  •   JAB    16 年前

    不是直接回答你的问题,而是如何:

    bool allTwo = a & b & c == 2;
    

    编辑:正如皮特所说,这行不通。这是怎么回事?

    bool allEqual(params int[] inputs)
    {
        int lastval = inputs[0];
        for (int i = 1; i < inputs.length; i++)
        {
            if (lastval != inputs[i])
                return false;
    
            lastval = inputs[i];
        }
    
        return true;
    }
    

    声明一次,只要您想用逗号分隔的整数列表进行比较,就可以使用它。(可能有一个更简单的函数,但是无论如何。)

    bool allTwo = a == b && b == c && c == 2; // prefer this format over a == 2 && b == 2 && c == 2, personally
    

    对战

    bool allTwo = allEqual(a, b, c, 2);
    

    关于你的问题本身,我真的没什么好说的,别人的回答中还没有提到。