New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow && with nullable boolean directly? #871

Closed
ryanelian opened this Issue Sep 1, 2017 · 15 comments

Comments

Projects
None yet
6 participants
@ryanelian
Copy link

ryanelian commented Sep 1, 2017

By definition, && (conditional-AND operator) performs logical AND of its boolean operands but short-circuits whenever it encounters false.

At the moment it cannot be done with a bool? operand:

bool a = true;
bool? b = true;

if (a && b) Console.WriteLine("Yes");
// error CS0019: Operator '&&' cannot be applied to operands of type 'bool' and 'bool?'

if (a && b == true) Console.WriteLine("Yes");
// Yes

It would be nice to be able to do this without doing b == true or b.GetValueOrDefault().

The same idea may also apply to || (conditional-OR operator) which short-circuits whenever it encounters true.

@HaloFour

This comment has been minimized.

Copy link
Contributor

HaloFour commented Sep 2, 2017

I don't understand what you're asking. The && and || operators do short-circuit the evaluation of the expressions. The error message you are receiving is because your expression is invalid and cannot be compiled because there is no overload of the && operator that can be applied between a type of bool and a type of Nullable<bool>. You can't "short-circuit" the compilation phase.

@svick

This comment has been minimized.

Copy link
Contributor

svick commented Sep 2, 2017

While && and || indeed don't work, & and | do. Though the result might not be what you would expect:

bool a = true;
bool? b = true;

if (a & b) Console.WriteLine("Yes");
// error CS0266 Cannot implicitly convert type 'bool?' to 'bool'. An explicit conversion exists (are you missing a cast?)

if ((a & b) == true) Console.WriteLine("Yes");
// Yes

Considering that the result of && would also have to be bool? would that actually help you? The code would be:

if ((a && b) == true) Console.WriteLine("Yes");
@ryanelian

This comment has been minimized.

Copy link
Author

ryanelian commented Sep 2, 2017

The error message you are receiving is because your expression is invalid and cannot be compiled because there is no overload of the && operator that can be applied between a type of bool and a type of Nullable. You can't "short-circuit" the compilation phase.

I might not be clear in the first place. I apologize for that.

That is actually what I'm asking, yes. Make && apply between Nullable<bool> and bool. Is that language feature or am I asking in the wrong place?

@HaloFour

This comment has been minimized.

Copy link
Contributor

HaloFour commented Sep 2, 2017

@ryanelian

This would be the correct place, but most language suggestions are challenged as the bar is set exceptionally high as to what are considered let alone implemented.

The C# team decided long ago that when it comes to bool? types that null is not false. This is why you cannot directly use a bool? variable in a condition. In your examples above if (b) { } would produce the same error message. The team wants you to be very explicit with what you mean in order to avoid bugs.

The only way for the && and || operator to be directly applicable to bool? variables would be to reverse this position. Then null would have to be false. I think that this is a bad idea.

@svick

This comment has been minimized.

Copy link
Contributor

svick commented Sep 2, 2017

@HaloFour I don't think that's true. Right now, && on bool and bool works like this (emulating expression evaluation using delegates):

bool AndAnd(Func<bool> leftFunc, Func<bool> rightFunc)
{
    if (leftFunc() == false)
        return false;
        
    return rightFunc();
}

And && on bool and bool? could work almost the same:

bool? AndAnd(Func<bool> leftFunc, Func<bool?> rightFunc)
{
    if (leftFunc() == false)
        return false;
        
    return rightFunc();
}

This should give the same results as & on bool and bool? currently does. And it does not reverse the "null is not false" position.

@HaloFour

This comment has been minimized.

Copy link
Contributor

HaloFour commented Sep 2, 2017

@svick

You can't make the grammar legal without reversing the position. The fact that the logic can execute deferred and that b might not be evaluated doesn't matter in the least at compile-time.

@ryanelian

This comment has been minimized.

Copy link
Author

ryanelian commented Sep 2, 2017

If the C# team has taken a stand that bool? would not be usable for those operators explicitly for the sake of being explicit, I can understand that.

However, since true value of bool? is actually true, I think that the quality-of-life when code writing can be improved when dealing with the data type instead of requiring developers to add == true manually when using the operators...

In my eyes, this is just a syntactic sugar: if you try to use nullable boolean with && or ||, the compiler should just silently add == true for convenience.

But that doesn't mean the compiler should let the programmer to negate ! the nullable boolean because I agree that null is not false. That's another can of worm for another time.

That said, I'll just close this issue quietly.

@ryanelian ryanelian closed this Sep 2, 2017

@jnm2

This comment has been minimized.

Copy link
Contributor

jnm2 commented Sep 2, 2017

At the end of the day, you are fitting a tri-state into a bi-state position. That means mapping null to either true or false. Since the language designers (I think wisely) decided not to allow that mapping to be implicit, that means you must be explicit about the mapping by choosing between == true or != false.

@svick

This comment has been minimized.

Copy link
Contributor

svick commented Sep 2, 2017

@HaloFour Why not? What's wrong with the following code?

bool a = true;
bool? b = true;

bool? c = a && b;

if ((a && b) == true) Console.WriteLine("Yes");

How specifically does the above code reverse the position?

I'm not suggesting that if (a && b) should be allowed, just that I don't see a reason why a && b couldn't be allowed.

@HaloFour

This comment has been minimized.

Copy link
Contributor

HaloFour commented Sep 2, 2017

@svick

I see, so you're suggesting that a && operator between bool? and bool? produces a bool?, as it does with &.

IIRC the problem with that is false & null and true | null are both null so the compiler still can't short-circuit and with the result being bool? you still can't use the result as a condition. So, it makes no sense to offer a second set of operators that would have to behave identically to the existing operators, especially if it implies that it woulkd behave differently. Either way it doesn't satisfy thus proposal.

@svick

This comment has been minimized.

Copy link
Contributor

svick commented Sep 2, 2017

@HaloFour

I see, so you're suggesting that a && operator between bool? and bool? produces a bool?, as it does with &.

Exactly. If this operator was to be added, I think that's the only reasonable way.

IIRC the problem with that is false & null and true | null are both null so the compiler still can't short-circuit

That's not right. false & null is false and true | null is true, so short-circuiting is possible.

and with the result being bool? you still can't use the result as a condition.

Right. I think it makes sense to add the operators for consistency, but I understand that's not a very compelling reason.

@HaloFour

This comment has been minimized.

Copy link
Contributor

HaloFour commented Sep 2, 2017

That's not right. false & null is false and true | null is true, so short-circuiting is possible.

Is that right? I might be thinking VB.NET which adopted more of an SQL approach.

@jrmoreno1

This comment has been minimized.

Copy link

jrmoreno1 commented Jun 5, 2018

@HaloFour : Both SQL and VB.Net do the same thing, and it is logically the only thing to do. False OR Null is null, True AND NULL is null. Both of these require the value of NULL to be know in order to come to a conclusion. (False AND NULL) is False and (True OR NULL) is True, because the null value does not need to be known, it is irrelevant.

@ali-hasani

This comment has been minimized.

Copy link

ali-hasani commented Jun 25, 2018

I used this solution:
"... bool parameter ..." || Convert.ToBoolean(... bool? parameter ...)

@jnm2

This comment has been minimized.

Copy link
Contributor

jnm2 commented Jun 25, 2018

@alihasaniGit Convert is an inefficient solution compared to (nullableBool ?? defaultValue). IIRC, Convert was a legacy class added to help folks transition from VB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment