C# conditional AND (&&) OR (||) precedence
S

6

89

We get into unnecessary coding arguments at my work all-the-time. Today I asked if conditional AND (&&) or OR (||) had higher precedence. One of my coworkers insisted that they had the same precedence, I had doubts, so I looked it up.

According to MSDN AND (&&) has higher precedence than OR (||). But, can you prove it to a skeptical coworker?

http://msdn.microsoft.com/en-us/library/aa691323(VS.71).aspx

bool result = false || true && false; // --> false
// is the same result as
bool result = (false || true) && false; // --> false
// even though I know that the first statement is evaluated as 
bool result = false || (true && false); // --> false

So my question is how do you prove with code that AND (&&) has a higher precedence that OR (||)? If your answer is it doesn't matter, then why is it built that way in the language?

Sponson answered 28/7, 2009 at 21:0 Comment(10)
It's that way in the language because they have to make a decision. Personally, I don't care which has precedence; I'd use parenthesis to make sure I'm getting the result I expect. It's not about why it does what it does; it's about being able to figure out what the code is doing when you back to it weeks, months or years later.Merrillmerrily
@Jeff: That's not correct. There is a mathematical basis for this decision - it's called boolean algebra.Jaborandi
I also wonder how often short circuiting is affecting these results vs how often its due to some sort of precedence. And how would you know? Hmm...Illustrator
@TheSteve: short-circuiting is not affecting expression result. It only affects side effects.Jaborandi
I think I know what you mean. I guess short circuiting is just something that requires you to write your test case carefully.Illustrator
The fact that you even have to consider it means you shouldn't rely on the next guy knowing, if there is a question that anyone in the office might possibly have to spend 3 seconds thinking about it, then invest the .5 seconds to add a ( and a )Heterogenetic
Let me see if I've got this straight. Your coworker has a belief about the language. That belief is contradicted by both the specification and the implementation. Your claim is consistent with the specification and the implementation. So why are YOU the one trying to construct a proof? The burden of proof is upon the person who has the crazy belief, not the person who has the sensible belief. I wouldn't waste any more time on this; if they want to spend their time trying to prove something false, let 'em.Sochi
"We get into unnecessary coding arguments at my work all-the-time." Well thats your problem. Being the right one is not as important as working together. The pragmatic solution is to use parenthesis to make it explicit.Islaen
I appreciated the eloquent expression of frustration with a couple of hypens "all-the-time"Augusto
The problem is not the specification or the example, but the stubborn coworker. You can give evidence forever but they won't believe it, you'll just waste time and effort. To save time, that kind of situation is easily handled with a huge bet: tell the stubborn person: 'I bet you $10,000 that it is as I say' and they will immediately step back. It easy to argue forever about things you are actually uncertain of, when it is for free. A pride thinghy. When it will cost them, they'll only insist if they are really sure. Plus the high sum will reassure them that you are really certain.Sordino
A
140

Change the first false by true. I know it seems stupid to have (true || true) but it proves your point.

bool result = true || true && false;   // --> true 
     result = (true || true) && false; // --> false
     result = true || (true && false); // --> true
Actinia answered 28/7, 2009 at 21:6 Comment(12)
Nice example of why it is important.Copenhagen
What if you reverse the order of the operators? Just to ensure that it isn't the result of some short-circuiting element.Pork
Short circuiting only ever occurs when the result of the boolean expression is known; short circuiting can not change the result of a boolean expression.Seaside
The above example doesn't prove the point because it ignores short-circuiting! Let's say we changed C# so that || had higher precedence than &&. Then true || true && false would STILL return true. Why? Because || will not evaluate the rest of the statement due to short-circuiting as stated in msdn.microsoft.com/en-us/library/aa691310(VS.71).aspxTelega
@James, no it would not.. If || had higher precedence, then the expression would be equivilent to (true || true) && false => False, not true, because thafter evaluating {true || true) as true, what would be left is true && false, which would NOT create a short circuitPointenoire
@Charles Bretana, in my understanding, true || true && false performs no operations. It simply returns true due to short-circuiting. The || and && operators are not evaluated.Telega
@James, No, if || had higher precedence the clr would evaluate this as (true or true) && false. so first it would evaluate (true || true). Within this expression, yes, short-circuiting occurs because for an OR expresion, if the first part is true, there is no need to evaluate the second part. So this evaluates to true. Now we have true && false. For && operations, short circuiting only occurs if the first part is FALSE, which in this case it is not, so both parts have to be true for A && B to evaulate as true. So it evaluates both parts and comes up with falsePointenoire
Could we just stop all this non-sense, which seems to repeat itself ad-nauseum?! Repeat with me : SHORT-CIRCUITING DOES NOT CHANGE RESULT. Short-circuiting only applies when the result is already known. SHORT-CIRCUITING ONLY AFFECTS SIDE-EFFECTSJaborandi
@Charles Bretana, my conjecture may have been made in haste, but I still stand by the fact that || and && are not evaluated in true || true && false. Run the code I posted as an answer and see the result. Try to come up with actual code to prove me otherwise.Telega
@EFraim. "Short-circuiting does not change result." I have never mentioned otherwise. I'm simply talking about the proof to the OP's coworker; the fact that JB King and myself are skeptical of this proof goes to show it is missing something. I know that the || and && are not evaluated at all; and if the OP's coworker knew that fact, then the coworker could simply say that the proof is illogical since it hinges upon all three statements evaluating all six operations. If you didn't know the only && operation that is actually evaluated is (true || true) && false.Telega
Short circuiting DOES change the result! Compare true | false & false with true | false && false. The first expression is true, but the second expression is false. Short circuiting will only keep the result the same if you use only short circuited operators in your expression.Shortsighted
@Shortsighted That isn't a result of short circuiting, but of changing the order of operation. The & operator has higher precedence than the | operator, so the first expression would behave like true | (false & false). This would evaluate to true because false & false = false, then false | true = true. However, the | operator has a higher precedence than the && operator, so the second expression would behave like (true | false) && false. This would evaluate to false because true | false = true, then true && false = false.Expense
H
14

If you really want to freak him out try:

bool result = True() | False() && False();

Console.WriteLine("-----");
Console.WriteLine(result);

static bool True()
{
    Console.WriteLine(true);
    return true;
}

static bool False()
{
    Console.WriteLine(false);
    return false;
}

This will print:

True
False
False
-----
False

Edit:

In response to the comment:

In C#, | is a logical operator that performs the same boolean logic as ||, but does not short-circuit. Also in C#, the | operator has a higher precedence than both || and &&.

By printing out the values, you can see that if I used the typical || operator, only the first True would be printed - followed by the result of the expression which would have been True also.

But because of the higher precedence of |, the true | false is evaluated first (resulting in true) and then that result is &&ed with false to yield false.

I wasn't trying to show the order of evaluation, just the fact that the right half of the | was evaluated period when it normally wouldn't be :)

Hued answered 28/7, 2009 at 21:35 Comment(4)
a. Why mixing boolean and bitwise operator? b. Why do you insist on printing it? What the order of evaluation has to do with it?Jaborandi
Response to response: | is still binary. It is just that for bool it performs the desired operation - as it does in C++. To clarify it MS documents it as logical for bool's. But IMHO it just muddies water.Jaborandi
This would be an amusing prank. :)Telega
So, if you change || to | and leave the &&, the result of the expression changes from true to false? So you'd normally either use | together with &, or use || together with &&.Shortsighted
D
6

Wouldn't this get you what you're after? Or maybe I'm missing something...

bool result = true || false && false;
Dulse answered 28/7, 2009 at 21:5 Comment(2)
This distinguishes between && having higher precedence and || having higher precedence, but does not distinguish between || having higher precedence and && and || having equal precedence. Remember that if operators are equal in precedence they are simply evaluated left-to-right.Reynoso
I should say though that this does work as a proof for C# in particular (or really any normal language), since the actual result you do get is unambiguous. It's just not a general method for working out the relative precedence in case you're up against an esoteric language that contradicts boolean algebra on purpose.Reynoso
J
5

You don't prove it with code but with logic. AND is boolean multiplication whereas OR is boolean addition. Now which one has higher precedence?

Jaborandi answered 28/7, 2009 at 21:8 Comment(15)
In some languages, neither one does (e.g. Smalltalk). Analogies can be deceiving.Lemieux
That's not analogy. That's reasoning behind this particular feature of C-family languages.Jaborandi
By the way the Smalltalk sample is not really representative: it has no operator precedence for math operators at all. In the same way you could argue they have the same precedence in Scheme.Jaborandi
Just let me undestand the reason for the downvote: a). You don't agree with principles of boolean algebra. b). You don't know what it is.Jaborandi
I don't know about the other downvoter, but I downvoted because this has nothing to do with the question. It happens to match... but anyone can design a language Foo# where this isn't true; how would your "proof with logic" work then? It might explain why this precedence was chosen, but it doesn't help establish that the compiler I have installed actually behaves that way.Verboten
@romkyns: It has everything to do with the language. C and C++'s rules derive from the laws of algebra. That's why + has smaller precedence than *. You can argue all you want but you are both wrong and obnoxious. Your compiler behaves according to the language specification and the language specification has it basis in algebra, Q.E.D.Jaborandi
QED? Do you know what it means to prove something? The language might be intended to follow the laws of algebra, but how do you prove that between that intention and the huge amount of engineering effort, nobody messed up and accidentally violated it or misread the spec when implementing the precedence rules? (unlikely, but not impossible)Verboten
@EFraim: Which algebra? You are assuming a specific algebra. The commonly-accepted algebra for regular expressions in theoretical computer science is equivalent to finite-state automata; according to your logic, therefore, .NET regular expressions should also be. But they are not! Q.E.D.!!! ;-)Tedmann
@Timwi: No, I am assuming what you have learned in either first or second grade. Principle of least surprise applies to programming language design too ;)Jaborandi
@EFraim: Exactly, it’s a principle. Not a law. Hence, your reasoning is a good guess, but not a proof.Tedmann
Also, I don’t believe you that you learnt Boolean algebra in first or second grade.Tedmann
@Timwi: My example related to addition/multiplication, in case I was not clear. To clarify - of course it's not a law, but neither it's an arbitrary decision of C's designers.Jaborandi
I think the point you are making is valid, it's just that it doesn't qualify as a "proof", where a proof is something much more rigorous than just explaining how and why the language designers decided to do things. "They based it on algebra, therefore it does necessarily work like algebra" is not a rigorous proof (and actually saying it that way is logically invalid).Cinelli
Also, how would you prove to the layman that AND is equivalent to multiplication and OR is equivalent to addition? Now you have two problems.Connotative
@tripleee: No need to prove anything, they are defined that way in Boolean algebra. I am talking C# layman here, not math layman.Jaborandi
C
2

false || true && true

Yields: true

false && true || true

Yields: true

Corncrib answered 28/7, 2009 at 21:7 Comment(1)
The first statement is going to return true no matter what order you do the operations in. The second will only return false if || is evaluated first. Since it does return true, either && is evaluated first, or they have the same precedence and are evaluated left-to-right. A third statement true || true && false (which also returns true) can only be true if && is evaluated first.Strawworm
T
-5

You cannot just show the end result when your boolean expressions are being short-circuited. Here's a snippet that settles your case.

It relies on implementing & and | operators used by && and ||, as stated in MSDN 7.11 Conditional logical operators

public static void Test()
{
    B t = new B(true);
    B f = new B(false);

    B result = f || t && f;

    Console.WriteLine("-----");
    Console.WriteLine(result);
}

public class B {
    bool val;
    public B(bool val) { this.val = val; }
    public static bool operator true(B b) { return b.val; }
    public static bool operator false(B b) { return !b.val; }
    public static B operator &(B lhs, B rhs) { 
        Console.WriteLine(lhs.ToString() + " & " + rhs.ToString());
        return new B(lhs.val & rhs.val); 
    }
    public static B operator |(B lhs, B rhs) { 
        Console.WriteLine(lhs.ToString() + " | " + rhs.ToString());
        return new B(lhs.val | rhs.val); 
    }
    public override string ToString() { 
        return val.ToString(); 
    }
}

The output should show that && is evaluated first before ||.

True & False
False | False
-----
False

For extra fun, try it with result = t || t && f and see what happens with short-circuiting.

Telega answered 28/7, 2009 at 23:38 Comment(1)
Short-circuiting has nothing to do with expression result. Can we just get over it?Jaborandi

© 2022 - 2024 — McMap. All rights reserved.