views:

210

answers:

5

Hi everyone,

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.

+15  A: 

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).
Andrew Hare
+9  A: 

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.

Bryan Watts
+3  A: 

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

Kevin
A: 

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.

ShellShock
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.
Anthony Pegram
+1  A: 

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)
{
    //....
}
Dan Tao
I think you ment: if (!conditionHolds)
riffnl
@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.)
Dan Tao