Link to home
Start Free TrialLog in
Avatar of lapucca
lapucca

asked on

Why am I getting a logical operator error?

if ((result <0) && !prevEnabled)

Here result is int type, and preEnabled is a bool? type.  I get error in VS with red underline, "Operator && cannot be applied to operands of type bool and bool?"

How code it so I can test result is less than zero and prevEnabled is false?

This is so odd that I can't do this .  Feels like I'm loosing my head with this error.
ASKER CERTIFIED SOLUTION
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
There is no error in your code.
Something  other issue is there.
Please copy paste the exact code, so quickly we will get the answer.

I tried with following and it's ok. No Error.
    class Program
    {
        static void Main(string[] args)
        {
            int result = 10;
            bool prevEnabled = true;

            if ((result < 0) && !prevEnabled) // Better ==> if ( (result < 0) && (!prevEnabled) )
            {
                Console.WriteLine("Yes!!!");
            }
            else
            {
                Console.WriteLine("No---");
            }

        }

Open in new window

>>There is no error in your code.

Oh yes there is.  Your example has an error - you do not use the same type of variables as the person asking the question.  See my previous comment.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Don't forget about the null coalescing operator...  ;)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EE_Q28585128
{
	class Program
	{
		static int result = 1;
		static bool? prevEnabled = true;

		static void Main(string[] args)
		{
			Console.WriteLine("Should be false: {0}", ((result < 0) && (prevEnabled ?? false)));
			result = -1;
			prevEnabled = null;
			Console.WriteLine("Should be false: {0}", ((result < 0) && (prevEnabled ?? false)));
			prevEnabled = true;
			Console.WriteLine("Should be true: {0}", ((result < 0) && (prevEnabled ?? false)));
			Console.ReadLine();
		}
	}
}

Open in new window


Procudes the following output -User generated image-saige-
@it_saige

I'm not sure that applies here. You are basically saying that null and false mean the same thing. They certainly could be if the requirement states such, but we don't know the requirement. Personally, I'd be wary of putting a coalesce in the condition of an if block--I'd set it out outside of the block first.
All true, however, the fact that the author is using a <Nullable>Bool value stipulates that if he/she is to use it as a comparison value, he/she *has* to declare that the null value of the <Nullable>Bool means something that can be compared against.

While my implementation above is the wrong comparison for what the user wants; the following is correct whether it is something as explicit as:
if ((result<0) && (prevEnabled.HasValue && prevEnabled.Value == false))

Open in new window

Or as short-handed as:
if ((result<0) && !(prevEnabled ?? true))

Open in new window

They mean the same thing:
using System;

namespace EE_Q28585128
{
	class Program
	{
		static int result = 1;
		static bool? prevEnabled = false;

		static void Main(string[] args)
		{
			Console.WriteLine("Has Value Version when result is greater than 0 and prevEnabled is false");
			Console.WriteLine("Should be false: {0}", ((result < 0) && (prevEnabled.HasValue && prevEnabled.Value == false)));
			Console.WriteLine();
			Console.WriteLine("Null-Coalescing Version when result is greater than 0 and prevEnabled is false");
			Console.WriteLine("Should be false: {0}", ((result < 0) && !(prevEnabled ?? true)));
			result = -1;
			Console.WriteLine();
			Console.WriteLine("Has Value Version when result is less than 0 and prevEnabled is false");
			Console.WriteLine("Should be true: {0}", ((result < 0) && (prevEnabled.HasValue && prevEnabled.Value == false)));
			Console.WriteLine();
			Console.WriteLine("Null-Coalescing Version when result is less than 0 and prevEnabled is false");
			Console.WriteLine("Should be true: {0}", ((result < 0) && !(prevEnabled ?? true)));
			prevEnabled = null;
			Console.WriteLine();
			Console.WriteLine("Has Value Version when result is less than 0 and prevEnabled is null");
			Console.WriteLine("Should be false: {0}", ((result < 0) && (prevEnabled.HasValue && prevEnabled.Value == false)));
			Console.WriteLine();
			Console.WriteLine("Null-Coalescing Version when result is less than 0 and prevEnabled is null");
			Console.WriteLine("Should be false: {0}", ((result < 0) && !(prevEnabled ?? true)));
			result = 1;
			Console.WriteLine();
			Console.WriteLine("Has Value Version when result is greater than 0 and prevEnabled is null");
			Console.WriteLine("Should be false: {0}", ((result < 0) && (prevEnabled.HasValue && prevEnabled.Value == false)));
			Console.WriteLine();
			Console.WriteLine("Null-Coalescing Version when result is greater than 0 and prevEnabled is null");
			Console.WriteLine("Should be false: {0}", ((result < 0) && !(prevEnabled ?? true)));
			Console.ReadLine();
		}
	}
}

Open in new window

Produces the following output -User generated image-saige-
They mean the same thing:
No, they do not.

prevEnabled.HasValue && prevEnabled.Value == false
Means that if prevEnabled has been given a value, and that value happens to be false.

prevEnabled ?? true
Means if prevEnabled has been given a value, and that value happens to be true, OR if prevEnabled was not given a value, then treat it as if it were assigned the value true. You've changed the semantics of what null means with this attempt. You do not do that in the first attempt. It's fine to change the semantics if that's what the requirement calls for.
You forgot the not operator:
!(prevEnabled ?? true)

Open in new window

In the explicit version HasValue, we can agree that HasValue returns false if prevEnabled is null and in the null-coalescing version if prevEnabled is null, then false is returned based on the not operator.

Now if prevEnabled does have a value, we look at the value itself.

If prevEnabled is true then the explicit version returns false.  And the null-coalescing version also returns false based on the not operator.

So again:
if (prevEnabled.HasValue && prevEnabled.Value == false)

Open in new window

And
if !(prevEnabled ?? true)

Open in new window

Produce the same results.

-saige-
Two points.
The asker is wanting to perform a check for prevEnabled and false.  Just a simple cast as I said in the first comment suffices and provides a solution.
The second is just in case to check for a null value should there be a possibility no value is assigned to the prevEnabled.  In that case the asker has made no indication of what is to be done should it in fact be null.  The suggestions later made are just wild guesses as to what is actually required.
My point is this, whether HasValue is used or a null-coalescing operation is used, the property, if null has to mean something in order for it to be used as a comparison.

-saige-
My somewhat veiled point is this:  These days, we write code for other programmers, not for the computer. Your code doesn't speak clearly to me as to why it's doing what it's doing. "If there's no value, then treat this as true." Why? Code should clearly display what it is doing; the comments are for why it's doing what it's doing. Why do I treat this as true if it's null? I can't tell from the code.

To be fair, my suggestion above could be argued against for the subtlety of how equality works, and you wouldn't get much argument from me. When I first started coding (in C#), I wrote the expanded checks (i.e. HasValue && Value == XXX). I happened across another programmer's code that used the short form, and it made me think about its simplicity. Since I understand why the equality check works, I use it. But even with this subtlety in how the equality check works, reading the code for the simplistic form still gives a pretty good indication of what is going on:  Does this thing contain the value false?

To be fairer, I'm not saying that the code you present is wrong on a technical level. It just may not be accurate. Coalesce is a great operator, but as with any tool it has its intended uses. Without knowing the requirements, it's impractical to determine whether or not its use applies here.

And no, I did not forget the negation. I think you're overlooking or ignoring my argument about semantics  ; )
You get no arguments from me on readability.  Matter of fact, I wanted to go back and edit my post to stipulate as such.  

From a readability standpoint and as something that is as easy on the eyes (as it is the brain ;) ), the expanded version works just as well and is most likely the better solution.  Is it more characters to type, certainly, but at first glance you can easily discern what is happening, whereas the null-coalescing operation takes a little more thought.

-saige-
Avatar of lapucca
lapucca

ASKER

The nullable is new for me since I haven't coded for almost 4 year.  Thank you very much.  I thought I was losing my head with this error.  It's fixed once I put (bool) in front of the bool? variable.
Avatar of lapucca

ASKER

Wow!  What have I started here...  Thank you everyone, I am learning a lot about this new nullable type and how to work with it.
Just be mindful of what Andy stated pertaining to that:

it will never be null when it reaches the if statement otherwise you need to test for that as well
Also, keep in mind that Nullable only works with value types (e.g. int, decimal, bool, etc.). It does not work with reference types--reference types are implicitly nullable. So the following would give a compiler error:

Nullable<string> s = ...

Open in new window

A nullable type is useful when there are three possibles - eg from a database.  True, false and no value such as a new record- when you might wish to hide controls.