This is the story of a C# language specification change.

The specification changed because the 1.0 version of the C# spec disagreed with itself, and one of those locations was incorrect and broke a feature.

The change is in the section on “Conditional Logic Operators”. Version 1 of the spec states:

The operation x && y corresponds to the operation x & y, except that y is evaluated only if x is true.

The operation x || y corresponds to the operation x | y, except that y is evaluated only if x is false.

The later versions (starting with version 3) state:

The operation x && y correspond to the operation x & y, except that y is evaluated only if x is not false.

The operation x || y correspond to the operation x | y, except that y is evaluated only if x is not true.

Why the change?

Well, a couple sections later, the spec defines “User-Defined Conditional Logical Operators”. The C# Language does not allow you to create a user defined operator && or operator ||. Instead, you must define operator |, operator &, operator true and operator false. Here is the pertinent text:

The && and || operation is evaluated by combining the user-defined operator true or operator false with the selected user-defined operator:

The operation x && y is evaluated as T.false(x) ? x : T.&(x,y), …... In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. Then, if x is definitely false, the result of the operation is the value previously computed for x. Otherwise, y is evaluated, and the selected operator & is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.

The operation x || y is evaluated as T.true(x) ? x : T.|(x,y), …... In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. Then, if x is definitely true, the result of the operation is the value previously computed for x. Otherwise, y is evaluated, and the selected operator | is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.

The key points here are that for operator &&, x is checked to ensure that it is not false, and for operator ||, x is checked to ensure that it is not true.

Why the spec had to change

The version 1.0 of the spec had serious limitations. User Defined Types that defined operator & or operator | would work with if and only if operator true and operator false were defined such that exactly one of them was true at all times.

Nothing in the language mandates that explicitly.

As a thought exercise, suppose you have a type that may be neither true nor false in some states. Maybe there are ranges of “true” and “false” and a range in between of “neither true nor false”.

If you want a concrete example, consider a type that has a single byte field. Its operator true returns true when all bits are 1. Its operator false returns true when all bits are 0. In all cases, to evaluate ‘x && y’, or ‘x || y’ requires both the left and right side of the operator. No short circuiting is possible.

That’s why the spec changed at version 3.

A little more explanation in the spec

We felt the spec needed a little more explanation around this change. In ECMA version 5, we’re adding this note:

note: The reason that short circuiting uses the 'not true' and 'not false' conditions is to enable user defined conditional operators to define when short circuiting applies. User defined types could be in a state where operator true returns false and operator false returns false . In those cases, neither && or || would short circuit.

The C# spec (thankfully) has relatively few locations where the spec disagrees with itself. But in a large document, it’s easy for them to creep in. Several people review and make corrections whenever we find them.