Why doesn't bool?
support lifted &&
and ||
? They could have lifted the true
and false
operators which would have indirectly added lifted &&
and ||
.
The operators |
and &
are already lifted and implement the correct Three-valued logic. But of course they are not short circuiting like ||
and &&
.
The question is why they decided not to lift those operators when creating the specification. So "It's like this because the spec says so" is no answer to the "why?".
When lifting true
and false
so that null
is neither true
nor false
:
public static bool operator true(bool? x)
{
return x.HasValue && x.Value
}
public static bool operator false(bool? x)
{
return x.HasValue && !x.Value
}
This would have resulted in &&
and ||
behaving just like their non short-circuiting counterparts. Except that false && anything
and true || anything
would short circuit (false
and true
are no compile time constants in these two examples).
This would work very similar to the DBBool example on MSDN.
I see no surprising or dangerous behavior introduced by lifting these operators. Did I miss something?
I have read another SO question on this, but found none of the answers satisfying.
Jeff Yates's answer shows a nice reason for why lifting the true
/false
operators isn't optimal, it doesn't explain why lifting &&
and ||
directly is bad. Since operator lifting is compiler magic that special cases Nullable<T>
it doesn't need to follow the overloading rules for normal types and thus would be able to offer &&
/||
without lifting true
.
For some Boolean operations, like exclusive or (XOR), it is not possible to short-circuit, because both operands are always required to determine the result. Short-circuit operators are, in effect, control structures rather than simple arithmetic operators, as they are not strict.
By short-circuiting, we mean the stoppage of execution of boolean operation if the truth value of expression has been determined already. The evaluation of expression takes place from left to right. In python, short-circuiting is supported by various boolean operators and functions.
Short-Circuit Evaluation: Short-circuiting is a programming concept in which the compiler skips the execution or evaluation of some sub-expressions in a logical expression.
C++ does use short-circuit logic, so if bool1 is false, it won't need to check bool2 . without short-circuit logic, it would crash on dereferencing a NULL pointer, but with short-circuit logic, it works fine.
What you propose would create two different usage patterns for nullable types.
Consider the following code:
bool? a = null;
// This doesn't currently compile but would with lifted true/false operators.
if (a)
{
}
// Whereas this provides a consistent use of nullable types.
if (a ?? false)
{
}
For consistency in the usage of nullable types, it makes sense to not lift the true
and false
operators on bool
. I don't know if this is the real reason why it wasn't done, but it makes sense to me.
Since you showed that lifting true
and false
is technically possible, there are only two possible answers to your question (with "they" being the people who wrote the compiler/spec):
if (myNullVar) { ... }
(with myNullVar
being a reference) doesn't work in C# (but it does in C/C++).I think there's always a balance between making a programming language more powerful and making it less error-prone.
Update: Just for you interest, that's what the official documentation says:
This is not allowed because it is unclear what null means in the context of a conditional.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With