【问题标题】:Or and And condition in same IF statement behaves differently [duplicate]相同 IF 语句中的 Or 和 And 条件的行为不同 [重复]
【发布时间】:2014-10-20 17:00:30
【问题描述】:

请在下面找到我的示例程序,

根据我的输入,条件 3 不应该为真。但它返回 true 并且 if 内部的语句正在执行。帮助我更好地理解这一点。

    static void Main(string[] args) {
        string temp = null;
        string temp1 = "0";
        string temp2 = "1";
        if (temp1 == "0" || temp2 == "2" && temp == null) {
            Console.WriteLine("Contion 1 satisfied");
        }
        if (temp1 == "0" || temp2 == "1" && temp == null) {
            Console.WriteLine("Contion 2 satisfied");
        }
        if (temp1 == "0" || temp2 == "1" && temp != null) {
            Console.WriteLine("Contion 3 satisfied");
        }
        if (temp1 == "1" || temp2 == "1" && temp != null) {
            Console.WriteLine("Contion 4 satisfied");
        }
        Console.ReadLine();
    }

提前致谢

【问题讨论】:

  • && 运算符的优先级高于 ||运算符
  • 提示:当我组合布尔运算符(AND 和 OR)时,我不想记住哪个在前,我总是使用括号。
  • @IVAAAN123: 但temp 为空。
  • @TimSchmelter 那又怎样?真 ||假 => 真
  • 括号是你的朋友temp1 || (temp2 && temp),除了产生正确的结果,它还可以在阅读你的代码时引入清晰

标签: c# .net


【解决方案1】:

我又太仓促了。该问题与运算符precedenceshort-circuit 对逻辑条件的评估有关:

  • 由于有优先级,语句的计算方式如下:

    (x || (y && z)) ~ (temp1 == "0" || (temp2 == "1" && temp != null))
    
  • 这里开始了短路评估 - 因为|| 运算符的左侧已经是true 例如。 temp1 == "0"右边的部分直接跳过了。

    操作

    x || y

    对应操作

    x | y

    除非 x 为真,否则不会计算 y,因为无论 y 的值如何,OR 运算都是真。这个概念被称为“短路”评估。

【讨论】:

  • 但是解释有误导性&&的优先级与它为什么是true的原因无关。那就是(恕我直言)OP 在问什么,为什么 && 不能按预期工作?原因是它从左到右进行评估,并且第一个条件(|| 的左侧)已经为真 -> 无需评估右侧。 msdn.microsoft.com/en-us/library/2bxt6kc4.aspx
  • 你甚至可以在没有得到DivideByZeroException:int zero = 0; if (temp1 == "0" || 100 / zero == 0 && 100 / zero == 0)的情况下编写这个条件。所以&& 在这个问题中根本不重要。
  • @TimSchmelter,我的错误,感谢您指出这一点,修复了答案。
  • 记住短路是一种优化。只要没有副作用,就不会改变结果。所以你可以把它关掉,结果还是一样的。
  • 当然优先级是最重要的。 && 具有更高的优先级这一事实正是您所描述的短路工作的原因。即x || y && z 等价于x || (y && z),因为&& 具有更高的优先级。如果|| 具有更高的优先级,它将等同于(x || y) && z,在情况4 中这将是错误的,完全符合OP 的预期。事实上,它实际上并不费心评估 (y&&z) 部分,这与这个问题完全无关,因为它只有在有副作用时才会产生实际影响。
【解决方案2】:

你在问为什么true || true && false 是真的。可以用两种方式解释:

从左到右:(true || true) && false --> 应该是假的,这是你所期望的。

但由于 && 具有更高的优先级,它被解释为:true || (true && false)。括号内为假,简化为true || false

这相当于为什么人类将5 + 3 * 8 读作5 + (3 * 8) 而不是(5 + 3) * 8

其他人提到短路评估。短路是一种优化技术,只要您评估的内容没有副作用,就不会改变实际答案。因此,如果关闭短路评估,结果将是相同的。

【讨论】:

  • 如果右侧可能有副作用,例如在左侧已经为真时抛出异常(int zero = 0; if (true || 100 / zero == 0 && 100 / zero == 0) 有效),则短路评估很重要。这也很重要,因为编译器不需要考虑运算符的优先级,因为短路评估和从左到右的评估顺序将阻止评估右侧(包括&&) .结论:在这种情况下,编译器不关心运算符的优先级。
  • 从左到右的评价是这样的:(true || true) && false。这并不妨碍右侧进行评估,恰恰相反。
【解决方案3】:

根据MSDN,运算符&&具有更高的优先级,所以:

  1. temp2 == "1" && temp != null 评估 false。备注:在这种情况下,由于惰性求值,这个条件永远不会被求值(条件temp1 == "1" 为真,所以不必检查第二个运算符 - 结果是已知的)。
  2. temp1 == "0" || false 评估 true(由于第一个条件)。

【讨论】:

  • 这里,运算符优先级也不是这个问题的答案,而是评估的顺序(从左到右)。 && 无关紧要,因为 temp == "1" 已经为真。
  • @TimSchmelter 我知道,它包含在第 1 点中。
  • 好吧,&& 的优先级在这里根本不重要,但它仍然是您回答的核心主题。实际上,第一个 || 背后的任何内容都没有得到评估,因为 temp2 == "1" 绝对是真的。
  • @TimSchmelter 为什么?考虑:true || true && false。如果 OP 不知道先例,他可以评估条件:true || true && false => true && false => false (由于先例有什么问题)。所以我认为优先级还是有问题的。
  • 关键是|| 的右边是什么并不重要,如果左边是真的。 Imho OP 也采取了错误的方式,因为他想知道为什么 true && false 没有产生 false
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
  • 1970-01-01
相关资源
最近更新 更多