I'm attempting to convert an object
to a bool
type and want to convert bool
and Nullable<bool>
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;
}
else
{
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 Nullable<bool>
doesn't inherit from object
(impossible) or that value is bool
will capture a bool?
.
It's also possible that ReSharper 2016 has a bug; I see that the implementation of System.Windows.Controls.BooleanToVisibilityConverter.Convert
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.
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.