Ben Russell Ben Russell - 1 year ago 41
C# Question

C# is operator with nullable types always false according to ReSharper

I'm attempting to convert an

to a
type and want to convert
types. I also want to make sure I make the appropriate casts where possible. So I have the following code:

if (value is bool)
boolValue = (bool) value;
else if (value is bool? && ((bool?)value).HasValue)
boolValue = ((bool?) value).Value;
throw new ArgumentException("Value must be a boolean type");

ReSharper 2016 informs me that
value is bool?
will always evaluate to false in this stack of if statements. Why is that? That would imply that
doesn't inherit from
(impossible) or that
value is bool
will capture a

It's also possible that ReSharper 2016 has a bug; I see that the implementation of
is pretty much identical. I doubt that WPF core would have such a mistake in it, leading me to believe it's an issue with ReSharper.

Answer Source

When a value type is stored as object it is boxed. Boxing of Nullable<T> gets special treatment:

Objects based on nullable types are only boxed if the object is non-null. If HasValue is false, the object reference is assigned to null instead of boxing ... Boxing a non-null nullable value type boxes the value type itself, not the System.Nullable that wraps the value type.

And, per the documentation for is:

An is expression evaluates to true if the provided expression is non-null, and the provided object can be cast to the provided type without causing an exception to be thrown.

So, using both of these you can deduce (see fiddle) that in the null case:

bool? x = null;
object obj = x;   // assigns obj = null
obj is bool?      // false, obj is null
obj is bool       // false, obj is null

And in the non-null case:

bool? x = true;
object obj =  x;  // obj is boxed bool (true)
obj is bool?      // true, obj unboxes to bool?
obj is bool       // true, obj unboxes to bool

So ReSharper is correct: your first branch will evaluate as true if value is true or false (whether the object was assigned from a bool or bool? is not relevant or even known). The second branch will always be false in this case.