为什么不能使用 is 运算符来区分 bool 和 Nullable<bool>?
Why is it not possible to use the is operator to discern between bool and Nullable<bool>?
我遇到了这个问题,很好奇为什么不能使用 is
运算符来区分 bool
和 Nullable<bool>
?例子;
void Main()
{
bool theBool = false;
Nullable<bool> theNullableBoolThatsFalse = false;
Nullable<bool> theNullableBoolThatsNull = null;
void WhatIsIt(object value)
{
if(value is bool)
Console.WriteLine(" It's a bool!");
if(value is Nullable<bool>)
Console.WriteLine(" It's a Nullable<bool>!");
if(value is null)
Console.WriteLine(" It's a null!");
}
Console.WriteLine("Considering theBool:");
WhatIsIt(theBool);
Console.WriteLine("Considering theNullableBoolThatsFalse:");
WhatIsIt(theNullableBoolThatsFalse);
Console.WriteLine("Considering theNullableBoolThatsNull:");
WhatIsIt(theNullableBoolThatsNull);
}
调用 Main()
给出;
Considering theBool:
It's a bool!
It's a Nullable<bool>!
Considering theNullableBoolThatsFalse:
It's a bool!
It's a Nullable<bool>!
Considering theNullableBoolThatsNull:
It's a null!
我希望;
Considering theBool:
It's a bool!
Considering theNullableBoolThatsFalse:
It's a Nullable<bool>!
Considering theNullableBoolThatsNull:
It's a null!
为什么 bool
和 Nullable<bool>
都匹配?
我尝试了什么;
- 我查阅了
Nullable
、is
、switch
和模式匹配的文档。
- 我认为这可能与传递到方法中的值的 unboxing 有关?
我认为它可能是 Nullable
所独有的,因为我没有 运行 遇到其他泛型类型的相同问题。例如;
void Main()
{
bool theBool = false;
List<bool> theListOfBool= new List<bool>();
void WhatIsIt(object value)
{
if(value is bool)
Console.WriteLine(" It's a bool!");
if(value is List<bool>)
Console.WriteLine(" It's a List<bool>!");
}
Console.WriteLine("Considering theBool:");
WhatIsIt(theBool);
Console.WriteLine("Considering theListOfBool:");
WhatIsIt(theListOfBool);
}
给予;
Considering theBool:
It's a bool!
Considering theListOfBool:
It's a List<bool>
我不是要解决问题。只是对为什么它以这种方式工作感兴趣。
到目前为止的答案表明是 implicit
和 explicit
转换导致了这种行为,但我无法通过以下示例进行复制;
class A
{
public static implicit operator A(B value) => new A();
public static explicit operator B(A value) => new B();
}
class B
{
public static implicit operator A(B value) => new A();
public static explicit operator B(A value) => new B();
}
static void Main(string[] args)
{
var a = new A();
var b = new B();
void WhatIsIt(object value)
{
if (value is A)
Console.WriteLine(" It's a A!");
if (value is B)
Console.WriteLine(" It's a B!");
}
Console.WriteLine("Considering a;");
WhatIsIt(a);
Console.WriteLine("Considering b;");
WhatIsIt(b);
}
给予;
Considering a;
It's a A!
Considering b;
It's a B!
is
的文档说:
It only considers reference conversions, boxing conversions, and unboxing conversions; it does not consider user-defined conversions or conversions defined by a type's implicit and explicit operators. The following example generates warnings because the result of the conversion is known at compile-time. Note that the is expression for conversions from int to long and double return false, since these conversions are handled by the implicit operator.
引用转换、装箱转换和拆箱转换是由框架决定的吗?
Nullable<T>
class 有 implicit and explicit operators implemented which are used in such cases out of the box, take a look at documentation
以下是 source code 的摘录:
[System.Runtime.Versioning.NonVersionable]
public static implicit operator Nullable<T>(T value) {
return new Nullable<T>(value);
}
[System.Runtime.Versioning.NonVersionable]
public static explicit operator T(Nullable<T> value) {
return value.Value;
}
值 false
可以安全地转换为 bool
和 bool?
,因为它们之间有一个隐式转换运算符。
另一方面,null
无法转换为 bool
,这就是为什么 null is bool
returns false
.
is
运算符不(也不能)关心您如何声明 变量——如果有的话。它只是指示在运行时 提供的值的类型。你也可以这样写:
WhatIsIt(false)
您希望该方法在这里表现如何?它只是尝试将值转换为两种类型 - 它可以 - 因此 returns 两者都为真。
为什么它对其他泛型不起作用,原因很简单,因为大多数泛型类型和它们的类型参数之间没有隐式转换。因此以下内容不起作用:
string myString = new List<string>();
申报时
Nullable<bool> theNullableBoolThatsFalse = false;
theNullableBoolThatsFalse
可以保存 'true'、'false' 或 'null' 同样 theNullableBoolThatsNull
可以保存布尔值和 Null。当您分配 Null 时,它完全变成 null can't be any other type 。它不指代任何对象。
Furthe Information About Nullable
bool
和 Nullable<bool>
在传递给您的方法时表现相同的原因是,每当您装箱 Nullable<T>
时,它实际上并没有装箱可为 null 的值,而是解包nullable 和 boxes that 的值。如果可为 null 的值为 null,那么您最终只会得到 null
,而不是 HasValue
是 false
的盒装 Nullable<T>
。
如果您装箱一个非空值,它只会装箱 Nullable<T>
的 Value
。所以从 WhatIsIt
的角度来看,前两个调用 几乎无法区分 ,因为 传入的是完全相同的值 。
这就留下了为什么 both is
检查 return true
的问题,即使在这两种情况下传入的内容,是一个带框的布尔值,而不是 Nullable<T>
。 C# 语言规范第 7.10.10 节回答了这个问题:
If T is a nullable type, the result is true if D is the underlying type of T.
在这种情况下,这是考虑 E is T
并且 D
之前定义为 E
的计算值,其中:
If the type of E is a nullable type, D is the underlying type of that nullable type.
这意味着 is
运算符 具体 定义为将可空类型视为等同于它们的基础类型,无论您如何混合和匹配实际值正在检查的类型以及您正在使用可为 null 的值检查的类型以及可为 null 的基础类型。
我遇到了这个问题,很好奇为什么不能使用 is
运算符来区分 bool
和 Nullable<bool>
?例子;
void Main()
{
bool theBool = false;
Nullable<bool> theNullableBoolThatsFalse = false;
Nullable<bool> theNullableBoolThatsNull = null;
void WhatIsIt(object value)
{
if(value is bool)
Console.WriteLine(" It's a bool!");
if(value is Nullable<bool>)
Console.WriteLine(" It's a Nullable<bool>!");
if(value is null)
Console.WriteLine(" It's a null!");
}
Console.WriteLine("Considering theBool:");
WhatIsIt(theBool);
Console.WriteLine("Considering theNullableBoolThatsFalse:");
WhatIsIt(theNullableBoolThatsFalse);
Console.WriteLine("Considering theNullableBoolThatsNull:");
WhatIsIt(theNullableBoolThatsNull);
}
调用 Main()
给出;
Considering theBool:
It's a bool!
It's a Nullable<bool>!
Considering theNullableBoolThatsFalse:
It's a bool!
It's a Nullable<bool>!
Considering theNullableBoolThatsNull:
It's a null!
我希望;
Considering theBool:
It's a bool!
Considering theNullableBoolThatsFalse:
It's a Nullable<bool>!
Considering theNullableBoolThatsNull:
It's a null!
为什么 bool
和 Nullable<bool>
都匹配?
我尝试了什么;
- 我查阅了
Nullable
、is
、switch
和模式匹配的文档。 - 我认为这可能与传递到方法中的值的 unboxing 有关?
我认为它可能是 Nullable
所独有的,因为我没有 运行 遇到其他泛型类型的相同问题。例如;
void Main()
{
bool theBool = false;
List<bool> theListOfBool= new List<bool>();
void WhatIsIt(object value)
{
if(value is bool)
Console.WriteLine(" It's a bool!");
if(value is List<bool>)
Console.WriteLine(" It's a List<bool>!");
}
Console.WriteLine("Considering theBool:");
WhatIsIt(theBool);
Console.WriteLine("Considering theListOfBool:");
WhatIsIt(theListOfBool);
}
给予;
Considering theBool:
It's a bool!
Considering theListOfBool:
It's a List<bool>
我不是要解决问题。只是对为什么它以这种方式工作感兴趣。
到目前为止的答案表明是 implicit
和 explicit
转换导致了这种行为,但我无法通过以下示例进行复制;
class A
{
public static implicit operator A(B value) => new A();
public static explicit operator B(A value) => new B();
}
class B
{
public static implicit operator A(B value) => new A();
public static explicit operator B(A value) => new B();
}
static void Main(string[] args)
{
var a = new A();
var b = new B();
void WhatIsIt(object value)
{
if (value is A)
Console.WriteLine(" It's a A!");
if (value is B)
Console.WriteLine(" It's a B!");
}
Console.WriteLine("Considering a;");
WhatIsIt(a);
Console.WriteLine("Considering b;");
WhatIsIt(b);
}
给予;
Considering a;
It's a A!
Considering b;
It's a B!
is
的文档说:
It only considers reference conversions, boxing conversions, and unboxing conversions; it does not consider user-defined conversions or conversions defined by a type's implicit and explicit operators. The following example generates warnings because the result of the conversion is known at compile-time. Note that the is expression for conversions from int to long and double return false, since these conversions are handled by the implicit operator.
引用转换、装箱转换和拆箱转换是由框架决定的吗?
Nullable<T>
class 有 implicit and explicit operators implemented which are used in such cases out of the box, take a look at documentation
以下是 source code 的摘录:
[System.Runtime.Versioning.NonVersionable]
public static implicit operator Nullable<T>(T value) {
return new Nullable<T>(value);
}
[System.Runtime.Versioning.NonVersionable]
public static explicit operator T(Nullable<T> value) {
return value.Value;
}
值 false
可以安全地转换为 bool
和 bool?
,因为它们之间有一个隐式转换运算符。
null
无法转换为 bool
,这就是为什么 null is bool
returns false
.
is
运算符不(也不能)关心您如何声明 变量——如果有的话。它只是指示在运行时 提供的值的类型。你也可以这样写:
WhatIsIt(false)
您希望该方法在这里表现如何?它只是尝试将值转换为两种类型 - 它可以 - 因此 returns 两者都为真。
为什么它对其他泛型不起作用,原因很简单,因为大多数泛型类型和它们的类型参数之间没有隐式转换。因此以下内容不起作用:
string myString = new List<string>();
申报时
Nullable<bool> theNullableBoolThatsFalse = false;
theNullableBoolThatsFalse
可以保存 'true'、'false' 或 'null' 同样 theNullableBoolThatsNull
可以保存布尔值和 Null。当您分配 Null 时,它完全变成 null can't be any other type 。它不指代任何对象。
Furthe Information About Nullable
bool
和 Nullable<bool>
在传递给您的方法时表现相同的原因是,每当您装箱 Nullable<T>
时,它实际上并没有装箱可为 null 的值,而是解包nullable 和 boxes that 的值。如果可为 null 的值为 null,那么您最终只会得到 null
,而不是 HasValue
是 false
的盒装 Nullable<T>
。
如果您装箱一个非空值,它只会装箱 Nullable<T>
的 Value
。所以从 WhatIsIt
的角度来看,前两个调用 几乎无法区分 ,因为 传入的是完全相同的值 。
这就留下了为什么 both is
检查 return true
的问题,即使在这两种情况下传入的内容,是一个带框的布尔值,而不是 Nullable<T>
。 C# 语言规范第 7.10.10 节回答了这个问题:
If T is a nullable type, the result is true if D is the underlying type of T.
在这种情况下,这是考虑 E is T
并且 D
之前定义为 E
的计算值,其中:
If the type of E is a nullable type, D is the underlying type of that nullable type.
这意味着 is
运算符 具体 定义为将可空类型视为等同于它们的基础类型,无论您如何混合和匹配实际值正在检查的类型以及您正在使用可为 null 的值检查的类型以及可为 null 的基础类型。