I know that || and && are defined as short-circuit operators in C#, and such behaviour is guaranteed by the language specification, but do |= and &= short-circuit too?
For example:
private bool IsEven(int n)
{
return n % 2 == 0;
}
private void Main()
{
var numbers = new int[] { 2, 4, 6, 8, 9, 10, 14, 16, 17, 18, 20 };
bool allEven = true;
bool anyOdd = false;
for (int i = 0; i < numbers.Length; i++)
{
allEven &= IsEven(numbers[i]);
anyOdd |= !IsEven(numbers[i]);
}
}
When the 9 entry is hit, allEven becomes false, meaning that all subsequent entries are irrelevant – the value of allEven is guaranteed to be false for all future calls to that expression. The same goes for anyOdd, which is set to true when it sees 9, and will remain true for all subsequent calls to that expression.
So, do &= and |= shortcut, or is IsEven guaranteed to be called on every iteration? Is there any defined behaviour in the language specification for this case? Are there any corner-cases where such short circuiting would be problematic?
The C# specification guarantees that both sides are evaluated exactly once from left-to-right and that no short-circuiting occurs.
The C# specification for compound operators says:
In your case
opis&or|. The short circuiting behavior mirrors that of&/|and not&&/||.Note that this only refers to behavior visible in a single threaded scenario. So if the right hand side has no side-effects that are observable in such a scenario, the compiler or JITter is still free to omit the evaluation.
In your example the compiler is free to terminate the loop once it knows the result, since there are no such side-effects. But it’s not required to do so.
In particular timing does not count as such a side-effect, and you thus can’t rely on your code having constant runtime. This can be problematic in a security context, since it can introduce a timing side-channel.