16

Is it safe to rewrite the following code:

bool b = foo.bar.HasValue ? foo.bar.Value : false;

to

bool b = foo.bar.Value ?? false;

where bar is the nullable type bool?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
radbyx
  • 9,352
  • 21
  • 84
  • 127

8 Answers8

31

The easiest fix there is

bool b = foo.bar.GetValueOrDefault();

which is also actually cheaper than .Value as it omits the has-value check. It will default to default(T) , which is indeed false here (it just returns the value of the underlying T field, without any checks at all).

If you need a different default to default(T), then:

var value = yourNullable.GetValueOrDefault(yourPreferredValue);
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 3
    Learn something new every day. Don't know how long I've been using `Nullable` and just not known about those methods. – anton.burger Jun 24 '11 at 13:00
18

What you want is:

bool b = foo.bar ?? false;

This is (surprisingly) safe and an intended use for the null-coalescing operator.

The ?? operator is called the null-coalescing operator and is used to define a default value for a nullable value types as well as reference types. It returns the left-hand operand if it is not null; otherwise it returns the right operand.

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

In the case of Nullable<T>, it is functionally equivalent to Nullable<T>.GetValueOrDefault(T defaultValue).

The code:

bool b = foo.bar.Value ?? false;

Will cause a compiler-error, because you cannot apply the operator to value types, and Nullable<T>.Value always returns a value-type (or throws an exception when there is no value).

Paul Turner
  • 38,949
  • 15
  • 102
  • 166
  • +1 for spotting the "will not compile" - although I disagree about "surprisingly" - mainly because 99% of the time I find myself using it on value types :) – Stuart Jun 24 '11 at 11:54
  • 1
    It's a surprise to many because the effective behaviour of null-coalesce changes depending on whether you're dealing with reference. For reference types, the IL is equivalent to `x == null ? x : false;`. For `Nullable`, ?? is replaced with a call to `GetValueOrDefault(T);`. Surprise! – Paul Turner Jun 24 '11 at 12:01
  • 3
    As useful as the reply currently marked as answer is, I feel this response is the actual answer to the OP's question. – Sameer Apr 08 '14 at 18:02
8

No - this is not safe.

The line:

bool b = foo.bar.Value ?? false;

will throw an InvalidOperationException if foo.bar has no value.

Instead use

var b = foo.bar ?? false;

Update - I just learned about .GetValueOrDefault(); from the other answers - that looks like a very good suggestion to use!


Update 2 - @ProgrammingHero's answer is also correct (+1 added!) - the line:

bool b = foo.bar.Value ?? false

actually won't compile - because of Error 50 Operator '??' cannot be applied to operands of type 'bool' and 'bool'

Stuart
  • 66,722
  • 7
  • 114
  • 165
  • 'foo.bar' is of type 'bool?', but 'foo.bar.Value' is just 'bool' which is the reason why you should apply the '??' operator to 'foo.bar' only - which has the correct type. Remember that '??' replaces null by the value you've specified which requires a nullable or a reference type, and bool is just a value type. – Matt Jul 23 '13 at 06:27
2

Nope.

The Value property returns a value if one is assigned, otherwise a System.InvalidOperationException is thrown.

From: http://msdn.microsoft.com/en-us/library/1t3y8s4s%28v=vs.80%29.aspx

So if hasValue is false then you will get an exception thrown in your second one when you try to run it.

Chris
  • 27,210
  • 6
  • 71
  • 92
2

ffoo.bar ?? false would be more safer to use

V4Vendetta
  • 37,194
  • 9
  • 78
  • 82
2
bar.Value ?? false

has compilation error, because left operand of ?? operator should be of reference or nullable type.

Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125
1

Maybe you have a look at this article in Stackoverflow too - it is an elegant null checking in the style obj.IfNotNull(lambdaExpression) - returning the object you want if obj is not null otherwise just null (but without throwing an exception).

I used it with the Entity Framework if you're accessing a referenced entity, e.g.

var str=Entity1.Entity2.IfNotNull(x=>x.EntityDescription) ?? string.Empty 

which returns EntityDescription contained in Entity2 which is referenced by Entity1 - or an empty string if any object Entity1 or Entity2 is null. Without IfNotNull you would get a long and ugly expression.

The extension method IfNotNull is defined there as follows:

public static TOut IfNotNull<TIn, TOut>(this TIn v, Func<TIn, TOut> f)
    where TIn : class 
    where TOut: class
{
    if (v == null) return null; else return f(v);
}

Update: If you update the code to C# version 6.0 (.NET Framework 4.6 - but seems to support older frameworks 4.x too), there is a new operator available which makes this task easy: The "elvis" operator ?..

It works as follows:

var str=(Entity1.Entity2?.EntityDescription) ?? string.Empty 

In this case, if Entity2 is null, evaluation stops and (...) becomes null - after which the ?? string.empty part replaces null by string.Empty. In other words, it works the same way as .IfNotNull(...) would.

Community
  • 1
  • 1
Matt
  • 25,467
  • 18
  • 120
  • 187
0

foo.bar.Value represents the non-nullable value when there is one, and throws an InvalidOperationException if there’s no real value.

Tomasz Jaskuλa
  • 15,723
  • 5
  • 46
  • 73