C# is operator with nullable types always false 根据 ReSharper

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

我正在尝试将 object 类型转换为 bool 类型并希望转换 boolNullable<bool> 类型。我还想确保在可能的情况下进行适当的转换。所以我有以下代码:

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 告诉我 value is bool? 在这堆 if 语句中总是求值为 false。这是为什么?这意味着 Nullable<bool> 不会从 object 继承(不可能)或者 value is bool 将捕获 bool?.

也有可能是ReSharper 2016有bug;我看到 System.Windows.Controls.BooleanToVisibilityConverter.Convert 的实现几乎相同。我怀疑 WPF 核心会不会有这样的错误,让我相信这是 ReSharper 的问题。

当值类型存储为 object 时,它是 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.

并且,根据 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.

所以,使用这两个你可以推断(见 fiddle)在 null 情况下:

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

在非空情况下:

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

所以 ReSharper 是正确的:如果 valuetruefalse(无论对象是从 boolbool? 不相关,甚至不为人知)。在这种情况下,第二个分支将始终是 false