Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Periodically, I wonder about this:

The short-circuit OR would always return the same value that the unshort-circuited OR operator would?

I expect that the short-circuit OR would always evaluate more quickly. So, was the unshort-circuited OR operator included in the C# language for consistency?

What have I missed?

share|improve this question
3  
Same return value - yes. Same side effects - no. –  Job Dec 25 '11 at 18:01
1  
Suppose f() raises an exception, consider true || f() and true | f(). Do you see the difference? The former expression evaluates to true, evaluation of the latter results in an exception being thrown. –  scarfridge Apr 20 '12 at 10:39

5 Answers 5

up vote 17 down vote accepted

Both operands were meant for different things, coming from C which didn't have a boolean type. The short-circuit version || only works with booleans, while the non-short circuit version | works with integral types, performing a bitwise or. It just happened to work as a non-short circuit logical operation for booleans which are represented by a single bit, being 0 or 1.

http://en.wikibooks.org/wiki/C_Sharp_Programming/Operators#Logical

share|improve this answer
7  
+1 for the link. When I read this question I was like "what?" since afaik the official name of these are logical and bitwise or, and not short-circuit and unshort-circuit which happen to be side-effects of how they work. –  stijn Dec 25 '11 at 10:21
    
+1 I see "operates on boolean operands only" - I possibly did not notice the difference because I only use expressions that evaluate to Boolean anyway –  Carnotaurus Dec 25 '11 at 11:16
1  
I had to check, but it is in fact true that the | operator, when applied to two boolean values, is compiled into the same or operator in CIL as it is when applied to two integer values - unlike || which is compiled into CIL using brtrue for a conditional jump. –  qes Dec 25 '11 at 11:20

| (the bitwise-or) must be non-short-circuit for types like int. That is because in almost all cases you need to calculate both sides of an | expression to calculate the correct result. For example, what is the result of 7 | f(x) ?

If f(x) is not evaluated, you cannot tell.

Furthermore it would be inconsistent to make this operator short-circuit for bool, when it is non-short-circuit for int. By the way, I think I have never used | for logical comparisons intentionally, finding it is very inconvenient to speak of | as a logical operator.

|| however is for logical comparisons, where short-circuit evaluation works fine.

The same is valid even for C and C++, where the origin of those operators is.

share|improve this answer

This is correct, the short-circuit OR operator (||) will always return the same value as the non-short-circuit OR operator (|). (*)

However, if the first operand is true, the short-circuit operator will not cause evaluation of the second operand, while the non-short-circuit operator will always cause evaluation of both operands. This can have an impact in performance, and sometimes in side-effects.

So, there is a use for both: if you care for performance, and the evaluation of the second operand does not produce any side effects, (or if you do not care about them,) then by all means use the short-circuit operator. But if for some reason you need the side-effects of the second operand, then you should use the non-short-circuit operator.

An example where you should use the non-short-circuit operator:

if( write_customer_to_database() != SUCCESS |
    write_supplier_to_database() != SUCCESS |
    write_order_to_database() != SUCCESS )
{
    transaction_rollback();
}

(*) Except for some really perverted scenario where the evaluation of the first operand to false causes by side-effect the the second operand to evaluate to true instead of false.

share|improve this answer
2  
+1 But I'd like to add that apart from using functions to indicate success or failure (as in your example): functions with side effects should generally be avoided... –  Marjan Venema Dec 25 '11 at 9:49
1  
Yes, that's probably why I have never used any of the non-short-circuit operators up until today, and the chances are slim that I ever will. –  Mike Nakis Dec 25 '11 at 9:58
    
That example depends on the operands being evaluated in strict left-to-right order. C# does guarantee this, but many similar languages (including C and C++) do not. –  Keith Thompson Dec 25 '11 at 10:18
    
Wouldn't short-circuit evaluation make sense for that particular example, since all the transactions will be rolled back if any of them fails? (I'm making some assumptions about the semantics of the calls.) –  Keith Thompson Dec 25 '11 at 10:20
    
@KeithThompson you are right, non-short-circuit evaluation will cause unnecessary processing, and in this sense the example is a bit lame, but it is not so lame as to warrant changing, because the truth remains that with short-circuit evaluation if write_customer_to_database() succeeds, then the rest of the write_... functions will never be called, and it is better to work correctly in the case of success, than to perform some unnecessary operations in the case of failure. –  Mike Nakis Dec 25 '11 at 11:25

if the right-hand clause of the operator have side-effect, and the programmer intended that he want both side effect to happen before checking their return value.

share|improve this answer
1  
Eek. Please don’t code like that … if you rely on side effects, have two different expressions, assign the results, and test them afterwards. –  Konrad Rudolph Dec 25 '11 at 16:02

there would be 2 reasons:

  1. keeping side effects (but that's clearer to code with a temporary variable)

  2. thwart timing attacks by avoiding the fork in the short circuit (this may even improve the runtime efficiency if the second operand is a variable but that is a micro-optimization)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.