tags:

views:

431

answers:

10

What is the reason null doesn't evaluate to false in conditionals?

I first thought about assignments to avoid the bug of using = instead of ==, but this could easily be disallowed by the compiler.

if (someClass = someValue) // cannot convert someClass to bool. Ok, nice

if (someClass) // Cannot convert someClass to bool. Why?

if (someClass != null) // More readable?

I think it's fairly reasonable to assume that null means false. There are other languages that uses this too, and I've not had a bug because of it.

Edit: And I'm of course referring to reference types

A good comment by Daniel Earwicker on the assignment bug... This compiles without a warning because it evaluates to bool:

bool bool1 = false, bool2 = true;
if (bool1 = bool2)
{
    // oops... false == true, and bool1 became true...
}
+16  A: 

It's a specific design feature in the C# language: if statements accept only a bool.

IIRC this is for safety: specifically, so that your first if (someClass = someValue) fails to compile.

Edit: One benefit is that it makes the if (42 == i) convention ("yoda comparisons") unnecessary.

Tim Robinson
But instead of saying "only accepts bool" it could say "does not accept assignment"...
simendsjo
Yeah, I find C#'s behavior preferable here, specifically because it protects you from that common bug
Tim Goodman
Assignment-as-condition is useful, albeit not so much in `if` statements: `while ((line = Console.ReadLine()) != null)`
Tim Robinson
The `if (a = b)` bug is not stopped by this, because `a` and `b` may be of type `bool`.
Daniel Earwicker
@simendsjo Except that you can assign in that expression, so it would assign first and then attempt to implicitly convert the object to a bool and would then (usually) fail.
Corey Ogburn
+5  A: 

One thing that comes to mind what about in the instance of a data type, like int? Int's can't be null, so do they always evaluate to true? You could assume that int = 0 is false, but that starts to get really complicated, because 0 is a valid value (where maybe 0 should evaluate to true, because the progammer set it) and not just a default value.
There are a lot of edge cases where null isn't an option, or sometimes it's an option, and other times it's not.

They put in things like this to protect the programmer from making mistakes. It goes along the same line of why you can't do fall through in case statements.

Kevin
+1NULL means that value is unknown or value is missing or value hasn't been assigned yet etc. it doesn't mean FALSE, semantically they are not the same. I always think treating NULL as FALSE is a bad language design.
Liwen
@Liwen I agree. On the surface, it seems like it could make sense, but there are just too many possibilities where null and false will differ.
Kevin
But a valuetype is not a reference type and cannot be null. I'm not saying that every possible type other than false should evaluate to true...
simendsjo
Right, but that is what I'm saying. if(object) does an evaluation as to if it's null, what are the rules around something which can't be null? It just gets really harry around the rules of making an assumption as to what you want to evaluate in an if(object) scenario.
Kevin
+4  A: 

As far as I know, this is a feature that you see in dynamic languages, which C# is not (per the language specification if only accepts bool or an expression that evaluates to bool).

I don't think it's reasonable to assume that null is false in every case. It makes sense in some cases, but not in others. For example, assume that you have a flag that can have three values: set, unset, and un-initialized. In this case, set would be true, unset would be false and un-initialized would be null. As you can see, in this case the meaning of null is not false.

Vivin Paliath
Losely typed ≠ dynamically typed. C++ evaluates `NULL` (a macro) to `0` which then evaluates to `false` in the `if` statement.
strager
I wasn't talking about `NULL`. I was talking about `null`. I don't see how my original statement is wrong. You normally do see `if(someVarThatCouldBeNull)` in dynamic languages.
Vivin Paliath
I agree, Vivin. I would say that the concept of null does not exist in C++. Or rather, the concept of a variable with no value (i.e. null in C#) does not exist in C++. A variable will always have a value, you just don't know what it is unless you initialize it yourself. As strager points out, NULL in C++ is just a macro to represent 0, nothing more. There are no special compiler rules around it.
Dr. Wily's Apprentice
@Dr. Wily's Apprentice. I was trying to say the same thing :) Thanks for explaining it though. I also was not sure why strager was talking about C++ - the question is about C#?
Vivin Paliath
+12  A: 

"I think it's fairly reasonable to assume that null means false"

Not in C#. false is a boolean struct, a value type. Value types cannot have a null value. If you wanted to do what you achieved, you'd have to create custom converters of your particular type to boolean:

public class MyClass
{
    public static implicit operator bool(MyClass instance)
    {
        return instance != null;
    }
}

With the above, I could then do:

if (instance) {

}

etc.

Matthew Abbott
You could also use the true or false operators, though they're a tad obscure: http://msdn.microsoft.com/en-us/library/6x6y6z4d%28VS.80%29.aspx
Dan Bryant
Dan Bryant
+4  A: 

Just use if(Convert.ToBoolean(someClass))

http://msdn.microsoft.com/en-us/library/wh2c31dd.aspx

Parameters

value Type: System.Object An object that implements the IConvertible interface, or null. Return Value

Type: System.Boolean true or false, which reflects the value returned by invoking the IConvertible.ToBoolean method for the underlying type of value. If value is null, the method returns false

Gage
+2  A: 

C# doesn't make a conversion of the parameter, as C++ does. You need to explicitly convert the value in a boolean, if you want the if statement to accept the value.

kiamlaluno
+11  A: 

"I think it's fairly reasonable to assume that null means false"

I don't agree. IMHO, more often than not, false means "no". Null means "I don't know"; i.e. completely indeterminate.

Rob Levine
+1 - does NULL *ever* mean false? I can't think of any examples of a technology that is implemented this way. There may be some that implicitly allow comparisons, but afaik, null never means false.
womp
While I'm not an expert on many different languages, I think NULL probably only ever "means" false in a language that doesn't properly handle NULL in the first place.
Dr. Wily's Apprentice
+2  A: 

Because null and false are different things.

A perfect example is bool? foo

If foo's value is true, then its value is true.
If foo's value is false, then its value is false
If foo has nothing assigned to it, its value is null.

These are three logically separate conditions.

Think of it another way
"How much money do I owe you?"
"Nothing" and "I don't have that information" are two distinctly separate answers.

diadem
+1 for good point, but still.. If you try to evaluate a bool? you either has to cast it to a bool and potentionally get a runtime error, or use == true / false to evaluate it... bool? is not a reference type as my question, it's still a valuetype
simendsjo
+3  A: 

What is the reason null doesn't evaluate to false in conditionals?

I first thought about assignments to avoid the bug of using = instead of ==

That isn't the reason. We know this because if the two variables being compared happen to be of type bool then the code will compile quite happily:

bool a = ...
bool b = ...

if (a = b)
    Console.WriteLine("Weird, I expected them to be different");

If b is true, the message is printed (and a is now true, making the subsequent debugging experience consistent with the message, thus confusing you even more...)

The reason null is not convertible to bool is simply that C# avoids implicit conversion unless requested by the designer of a user-defined type. The C++ history book is full of painful stories caused by implicit conversions.

Daniel Earwicker
I already updated my question with this from your previous comment. The implicit conversion argument is the best I've hear so far.
simendsjo
+1  A: 

It's simply the type system of c# compared to languages like PHP, Perl, etc.

A condition only accepts Boolean values, null does not have the type Boolean so it doesn't work there.

As for the NULL example in C/C++ you mentioned in another comment it has to be said that neither C nor C++ have a boolean type (afair C++ usually has a typecast for bool that resolves to an int, but thats another matter) and they also have no null-references, only NULL(=> 0)-pointers.

Of course the compiler designers could implement an automatic conversion for any nullable type to boolean but that would cause other problems, i.e.:

Assuming that foo is not null:

if (foo)
{
  // do stuff
}

Which state of foo is true?
Always if it's not null?
But what if you want your type to be convertable to boolean (i.e. from your tri-state or quantum-logic class)?

That would mean you would have two different conversions to bool, the implicit and the explicit, which would both behave differently.

I don't even dare to imagine what should happen if you do

if (!!foo) // common pattern in C to normalize a value used as boolean,
           // in this case might be abused to create a boolean from an object
{
}

I think the forced (foo == null) is good since it also adds clarity to your code, it's easier to understand what you really check for.

dbemerlin