Short circuiting statement evaluation -- is this guaranteed? [C#]
Asked Answered
I

6

17

Quick question here about short-circuiting statements in C#. With an if statement like this:

if (MyObject.MyArray.Count == 0 || MyObject.MyArray[0].SomeValue == 0)
{

//....
}

Is it guaranteed that evaluation will stop after the "MyArray.Count" portion, provided that portion is true? Otherwise I'll get a null exception in the second part.

Illustrational answered 22/4, 2010 at 15:27 Comment(1)
In case you're asking this question because you did get a null reference exception from the above code, it's likely either because MyArray is null or MyArray[0] contains a null. See my answer.Culdesac
F
37

Yes, this is guaranteed.

C# Language Specification - 7.11 Conditional logical operators:

The && and || operators are called the conditional logical operators. They are also called the "short-circuiting" logical operators.

Therefore they will support logical short-circuiting by definition - you can rely on this behavior.

Now it is important to make a distinction between a conditional operator and a logical operator:

  • Only conditional operators support short-circuiting, logical operators do not.
  • C#'s logical operators look just like their conditional counterparts but with one less character so a logical OR is | and a logical AND is &.
  • Logical operators can be overloaded but conditional operators cannot (this is a bit of an technicality as conditional operator evaluation does involve overload resolution and this overload resolution can resolve to a custom overload of the type's logical operator, so you can work around this limitation to a certain extent).
Freshet answered 22/4, 2010 at 15:28 Comment(1)
Where is the language specification?Kazantzakis
D
12

Yes, it is guaranteed.

http://msdn.microsoft.com/en-us/library/6373h346%28v=VS.80%29.aspx

The conditional-OR operator (||) performs a logical-OR of its bool operands, but only evaluates its second operand if necessary.

Disintegration answered 22/4, 2010 at 15:28 Comment(0)
M
5

Yes, it is guaranteed, but you can still get a null reference exception if MyArray is null (or MyObject for that matter obviously).

Moselle answered 22/4, 2010 at 15:31 Comment(0)
C
2

Just a small observation.

You said this:

Otherwise I'll get a null exception in the second part. (emphases mine)

This isn't true, actually. If short-circuiting weren't guaranteed, you could get an IndexOutOfRangeException in the second part.

It's still possible you could get a NullReferenceException, if the first item in your MyArray object is actually null (or if any of the other objects in that expression are).

The only totally safe check would be this:

bool conditionHolds =
    MyObject == null ||
    MyObject.MyArray == null ||
    MyObject.MyArray.Count == 0 ||
    MyObject.MyArray[0] == null ||
    MyObject.MyArray[0].SomeValue == 0;

if (conditionHolds)
{
    //....
}
Culdesac answered 22/4, 2010 at 16:19 Comment(2)
I think you ment: if (!conditionHolds)Bergerac
@riffnl: No, I was just making my example consistent with the OP's code. (He/she seems to want the code to do something in the negative case.)Culdesac
L
2

Yes,

For AND operations if any of the operand evaluated to false then total expression evaluated to false then there is no need to evaluate remaining expressions, And in case of OR operation if any of the operand evaluated to true then remaining evaluation can be skipped

So by using && or || operator, whole expression can be evaluated to true or false without evaluating all sub expressions.

But consider its side effects as well. This article might be helpful to understand short-circuit evaluation in depth with some real world examples.

Listel answered 1/5, 2016 at 6:59 Comment(0)
G
-1

I prefer to use the && operator, because you then test a positive (my array contains items), rather than negative (my error does not contain items):

if (MyObject.MyArray.Count > 0 && MyObject.MyArray[0].SomeValue == 0) 
{ 

//.... 
} 

This is also guaranteed to short-circuit.

Geanine answered 22/4, 2010 at 15:36 Comment(1)
The result of this code is not the same as his, though. In his, if the count is 0, it short circuits and enters the block. In yours, it only enters the block on the value of the first element being 0.Annotation

© 2022 - 2024 — McMap. All rights reserved.