tags:

views:

501

answers:

14

a bool variable could hold true or false, while bool? could be null as well.

Why would we need a third value for bool ? If it is not true, what ever it is, it is == false

Can you suggest a scenario where I would fancy a bool? instead.

Thanks

+8  A: 

a null value means "no value" or "unknown value". In this case, it's not true nor false, but undefined.

See: http://en.wikipedia.org/wiki/Many-valued_logic

nickf
Some people call a `bool?` a tristate. :-)
Chris Jester-Young
+1  A: 

being nullable could indicate that the bool has not be set or initialized if that is something your program might need to know

Bert Lamb
+3  A: 

it could be unknown in addition to true or false..in database land a NULL usually means unknown or no value

SQLMenace
+15  A: 

Something can be true, false or undefined for many reasons. How would one answer "Is your third child a girl?" if one only has two children? Both true and false are incorrect. Null would be appropriate as saying that the comparison doesn't apply.

Lee
Or an enum is perhaps a better choice.
kenny
There is only one appropriate response to that question: MU.
Noon Silk
+3  A: 

Lazy programming!

public bool MyProp
{
    get { return (myProp = myProp ?? GetPropValue()).Value; }
}
private bool? myProp;
ChaosPandion
grossssss! but cool! :)
Pestilence
A: 

Well I could see it being used as a "Not determined yet" kind of thing, i use bools all the time and sometimes just two values isnt enough!! for instance:

bool? bl;

bl = true; //Yes

bl = false; //No

bl = null; // Not determined, so do nothing

in my opinion its just the third value to a bool.

Tommy
we can do the same for a bool: bool b == null; ???
Asad Butt
@Asas, bool is a non nullable value type, bool b = null won't compile, hence the need for bool? (System.Nullable<bool>)
Paul Creasey
@Asad, if you try to do anything with an unitialized `bool`, you will get an `unassigned variable` error when you compile.
jball
Hah, @Paul beat me to it.
jball
A: 

You'd want to use that to cover the situation of "what if the user doesn't specify neither true nor false?"

It's just a way to cover all possible outcomes.

Serg
+2  A: 

a null value means

  • I don't know.
  • Insufficient data at this time
  • The state of the cat before the box is opened
  • I haven't made up my mind yet
  • Profit

a null value means Mu

John Knoeller
+4  A: 

It's good for when something hasn't been answered yet - think of a questionnaire. You have a list of y/n questions and only some have been answered. You wouldn't want to post true or false to the database table because the user hasn't answered the question yet.

George Handlin
A: 

Let's say that an order has been placed but not shipped yet. What is the value of Order.ShippedDate?

The old-fashioned way to handle this was to use a magical value like DateTime.MinValue. There were other ways to solve this problem (for example a wrapper type or an additional bool flag indicating that the order has not shipped yet). None of these is very satisfactory. What is needed is a uniform way to handle the problem of a missing or unknown value.

So the modern approach is to allow Order.ShippedDate to take on a value that semantically captures that the order has not shipped yet. That's the role that nullable types play. Semantically you should think of an instance of Nullable<T> with HasValue being false as representing "missing" or "unknown."

Further, databases have long allowed a column to allows null. For example, you could have an integer-valued column that allows null. How do you interact with such a column from code if you don't allow nullable ints? Again, you could use the approaches mentioned above but it is so much nicer when the language has a built-in facility for semantically capturing the situation that we are trying to model.

Jason
A: 

Here is another use case. Think of a hierarchical data structure that has a boolean property. Setting such property on the parent will apply to all of its children, unless those are set explicitly. Think Read only permissions for files and folders in Windows (which DO have a tri-state checkbox).

Parent1(readonly: true, evaluates true)
  |-Parent2(readonly: null, evaluates true)
    |-Child1(readonly: false, evaluates false)
    |-Child2(readonly: null, evaluates true)
 |-Parent3(readonly: false, evaluates false)
    |-Child1(readonly: false, evaluates false)
    |-Child2(readonly: null, evaluates false)
Igor Zevaka
A: 

I think the primary motivation (at least it was presented like this :-)) for adding nullable types in C# 2 were databases. In database, any data type can have the NULL value and when mapping these to C#, this is a problem. Nullable types allow you to deal with this quite elegantly - you can use int?, bool? and others. They are used for example in LINQ to SQL.

What does the third value mean for booleans, that of course depends on the application. I guess that typically, it will mean that the value/field is not available.

Tomas Petricek
+5  A: 

Various answers discuss the importance of nullable types in general. There is an additional answer for the nullable boolean, specifically. It's hard to understand in C#, but very easy to understand if you look at null-valued logic in any database.

Let's say you're tracking a list or table of Shipments. A Shipment has a DeliveryDate, but of course you don't know this information until long after the shipment has been made, and probably at least a few days after the shipment was actually delivered, when UPS finally gets around to notifying you. So of course the DeliveryDate is a Nullable<DateTime> (or DateTime?).

You want to retrieve a list of all shipments that were delivered during the last week. So you write this:

var deliveredThisWeek = shipments.Where(s => 
    s.DeliveryDate >= DateTime.Today.AddDays(-7));

Should shipments with a null delivery date be included? (The answer is, of course, no.)

OK, so what about this:

var deliveredBeforeThisWeek = shipments.Where(s =>
    s.DeliveryDate < DateTime.Today.AddDays(-7));

Should shipments with a null delivery date be included in these results? The answer is still no.

So now you have a curious situation. You might think that between the two of these queries, you would receive all shipments in the system. A | !A is always true, right? Not when you're dealing with nulls.

Even this one fails to get you all the results:

var deliveredAnytime = shipments.Where(s =>
    (s.DeliveryDate >= DateTime.Today.AddDays(-7)) ||
    (s.DeliveryDate < DateTime.Today.AddDays(-7)));

So how is this possible?

In order to accurately represent this logic, you need a condition that is not true or false. And again, C# is kind of a bad example here because it doesn't implement the logic the way you'd really expect it to. But in SQLese, it makes sense, because:

[DeliveryDate >= BeginningOfWeek] = NULL
[DeliveryDate <  BeginningOfWeek] = NULL

Clearly, NULL OR NULL is still NULL, not TRUE. That is how you can correctly say that a shipment was not delivered before the beginning of the week, and was not delivered after. Or, more accurately, we don't know when it was delivered, so we can't safely say that it does match either of those conditions.

But C# is not so consistent. In C#, if the DeliveryDate is null, then:

(s.DeliveryDate >= beginningOfWeek) == false
(s.DeliveryDate < endOfWeek) == false

Which gets you the right answer for our query above, so you might be tempted to say that regular boolean logic is good enough, except that this one messes it all up:

var deliveredThisWeek = shipments.Where(s =>
    !(s.DeliveryDate < DateTime.Today.AddDays(-7));

Aha... now it's giving us back null delivery dates! This isn't right! And before someone says "@Aaronaught, what are you on about, of course it's right! Those shipments were NOT delivered before last week, so the condition should cover them!", stop and think about it for a second.

The NULL doesn't actually mean that they weren't delivered. The NULL means that we don't know when they were delivered. It's possible that a clerk will pick up the confirmation tomorrow, and fill in the DeliveryDate as two weeks ago, invalidating the data we just picked up. There should not be null instances coming back from that query, and yet there are. If you wrote the same query in SQL, those results would be excluded.

So, why should you care about Nullable<bool> when C# apparently doesn't? So you can avoid falling into this trap in your own code:

public static bool? IsThisWeek(DateTime? dt)
{
    return (dt != null) ? (bool?)(dt.Value > DateTime.Today.AddDays(-7)) : null;
}

var deliveredBeforeThisWeek = shipments.Where(s =>
    (!IsThisWeek(s.DeliveryDate) == true));

// Or, the equivalent:
var alsoDeliveredBeforeThisWeek = shipments.Where(s =>
    (IsThisWeek(s.DeliveryDate) == false));

This is a bit awkward, but correct. We've written a query that more or less communicates its intent properly, and (bool?)null does not equate to true or false, so we get the right results in both cases.

If you ever need to evaluate a condition where the answer might be "I don't know" - use a bool? (AKA Nullable<bool>) as the result.

That way, the caller can decide how to handle an "I don't know" response instead of you simply choosing a default. Anything else means your class is lying.

Aaronaught
+1  A: 

I used it in a Filter Value. Basically I have a bool field in the database, but I wanted three states: Only return rows where the value is true, only return rows where the value is false, do not filter and return all rows.

Without a nullable bool I would have to use either an enum or a second bool to determine "Filter by this field yes/no" which would add bloat.

Michael Stum