0

Please find my sample program below,

Condition 3 should not be true as per my inputs. But it returns true and statement inside if is getting executed. Help me to have better understanding of this.

    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();
    }

Thanks in advance

leppie
  • 115,091
  • 17
  • 196
  • 297
UvarajGopu
  • 27
  • 9
  • && operator has higher priority than || operator – IVAAAN123 Aug 27 '14 at 07:48
  • 5
    A tip: When I combine boolean operators (ANDs and ORs) I don't want to remember which goes first, I *always* use brackets. – Hans Kesting Aug 27 '14 at 07:48
  • @IVAAAN123: but `temp` is null. – Tim Schmelter Aug 27 '14 at 07:48
  • @TimSchmelter so what? true || false => true – IVAAAN123 Aug 27 '14 at 07:49
  • 1
    brackets are your friend `temp1 || (temp2 && temp)`, Aside from producing the correct result, it also introduces clarity when reading your code – Sayse Aug 27 '14 at 07:49
  • The first || separates two conditions: 1) `temp1 == "0"` 2) `temp2 == "1" && temp != null`. Since the first is already true, the second doesn't need to be evaluated. – Tim Schmelter Aug 27 '14 at 07:49
  • @TimSchmelter at first calculated temp2 == "1" && temp != null, because && has higher priority – IVAAAN123 Aug 27 '14 at 07:50
  • @IVAAAN123: no, `true || false` --> `true` – Tim Schmelter Aug 27 '14 at 07:50
  • @TimSchmelter you are right, because of this he receives true at condition 3 – IVAAAN123 Aug 27 '14 at 07:52
  • @IVAAAN123: no, from left to right, since `temp1 == "0"` is already true the second condition doesn't need to be evaluated. And yes, if it has to be evaluated the `&&` had a higher precedence. – Tim Schmelter Aug 27 '14 at 07:53
  • @TimSchmelter just see answers, maybe they give explanation for you.. – IVAAAN123 Aug 27 '14 at 07:54
  • @TimSchmelter: The only reason the short circuiting works as you've described is because `&&` has a higher priority. Your comment where you separate the two conditions is only valid because `&&` has higher precedence and thus is grouped together as a single statement. Compare to `false && true || true`. Here by your left to right logic that would evaluate to false due to short circuiting. In fact though it splits it as `(false && true) || true`. You are right that the short circuiting means it doesn't have to bother evaluating the `&&` but that isn't why the result is what it is. – Chris Aug 27 '14 at 09:10

3 Answers3

3

I was too hasty, yet again. The issue has to do with both operator precedence and short-circuit evaluation of the logical condition:

  • because of the precedence, the statement is evaluated as follows:

    (x || (y && z)) ~ (temp1 == "0" || (temp2 == "1" && temp != null))
    
  • and here the short-circuit evaluation kicks in - because left side of the || operator is already true e.g. temp1 == "0" the right part is simply skipped.

    The operation

    x || y

    corresponds to the operation

    x | y

    except that if x is true, y is not evaluated because the OR operation is true regardless of the value of y. This concept is known as "short-circuit" evaluation.

Yurii
  • 4,811
  • 7
  • 32
  • 41
  • But the exlplanation is misleading The precendece of `&&` has nothing to do with the reason why it is `true`. That is (imho) what OP is asking, why does `&&` not work as expected? The reason is that it gets evaluated from left to right and the first condition (left side of `||`) is already true -> no need to evaluate the right side. http://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx – Tim Schmelter Aug 27 '14 at 07:55
  • You could even write this condition without getting an `DivideByZeroException`: `int zero = 0; if (temp1 == "0" || 100 / zero == 0 && 100 / zero == 0)`. So the `&&` does not matter at all in this question. – Tim Schmelter Aug 27 '14 at 08:08
  • Remember that short-circuit is an optimization. As long as there are no side-effects, it will not change the outcome. So you can turn it off and the outcome will be the same. – FarmerBob Aug 27 '14 at 08:44
  • Surely precendence is most important. The fact that `&&` is of higher precedene is exactly why the short circuiting works as you've described. ie `x || y && z` is equivalent to `x || (y && z)` because `&&` has higher precedence. If `||` had higher precedence it would be equivalent to `(x || y) && z` which would be false in case 4 exactly as the OP expected. The fact that it doesn't actually bother to evaluate the `(y&&z)` part is totally irrelevant in this questions since it only makes a practical difference if there are side effects. – Chris Aug 27 '14 at 08:50
  • I deleted the comment I had here just now. Precendence is totally the reason for this to work. short circuit is why it won't bother to evaluate the `&&` part but precedence is why it can group that part together as a single operand for the || operator. – Chris Aug 27 '14 at 09:11
  • Thanks for the new edit, @Yuriy. Now got my +1. – Chris Aug 27 '14 at 09:23
1

You are asking why true || true && false is true. It could be interpreted in two ways:

Left-to right: (true || true) && false --> should be false, which is what you are expecting.

But due to && having higher precedence, it is being interpreted like this: true || (true && false). The part in parenthesis is false, so that simplifies to true || false.

It is equivalent to why humans read 5 + 3 * 8 as 5 + (3 * 8) and not (5 + 3) * 8.

Others mentioned short-circuit evaluation. Short-circuit is an optimization technique, and will not change the actual answer as long as what you're evaluating has no side effects. So if short-circuit evaluation was turned off, the outcome would be the same.

FarmerBob
  • 1,314
  • 8
  • 11
  • Short-circuit evaluation matters if the right side could have side effects like throwing an exception if the left side was already true(`int zero = 0; if (true || 100 / zero == 0 && 100 / zero == 0)` works). It matters also because the precedence of the operators does not need to be taken into account by the compiler since the short-circuit evaluation and the left-to-right order of evaluation will prevent the right side(including `&&`) from being evaluated. Conclusion: the compiler does not care about operator precedence in this case. – Tim Schmelter Aug 27 '14 at 08:57
  • Left-to-right evaluation is this: `(true || true) && false`. This does not prevent the right side from evaluating, just the opposite. – FarmerBob Aug 27 '14 at 09:05
0

According to MSDN, operator && has greater priority, so:

  1. temp2 == "1" && temp != null evaluates false. Remarks: in this case, this condition would never be evaluted due to lazy evaluation (the condition temp1 == "1" is true, so the second operator don't have to be checked - result is already known).
  2. temp1 == "0" || false evaluates true (due to first condition).
  • Here also, the operator precedence is not the answer to this question but the order of evaluation (from left to right). The `&&` doesn't matter because `temp == "1"` is already true. – Tim Schmelter Aug 27 '14 at 08:11
  • 1
    @TimSchmelter I know, it is included in point 1. –  Aug 27 '14 at 08:18
  • well, the precedence of `&&` does not matter at all here but it's still the core topic of your answer. Actually nothing behind the first `||` gets evalauted because `temp2 == "1"` is definitely true. – Tim Schmelter Aug 27 '14 at 08:26
  • @TimSchmelter why? consider: `true || true && false`. If OP doesn't know the precedense, he could evalute the condition: `true || true && false` => `true && false` => `false` (what is wrong due to precednce). So I think that the precednce still has matter. –  Aug 27 '14 at 08:31
  • The point is that it doesn't matter what is on the right side of `||` if the left side is definitely true. Imho OP has also taken the wrong way because he wondered why the `true && false` didn't yield `false`. – Tim Schmelter Aug 27 '14 at 08:39
  • I agree that it doesn't matter what is on the right side of `||` but still: he could evalute also the condition like in my comment above - where precedence has matter. –  Aug 27 '14 at 08:41