有人可以解释为什么可以在null
实例上调用方法吗?
int? num = null;
var s1 = num.ToString();
var s2 = num.HasValue;
var s3 = num.GetHashCode();
var s4 = num.GetValueOrDefault();
var s5 = num.Value; // InvalidOperationException
var s6 = num.GetType(); // NullReferenceException
我可以在调试模式下检查num
是否为null
,那么如何在{{1}上调用ToString
方法或HasValue
getter }实例,但是对于null
和Value
是不可能的吗?它们都是GetType
类型的方法或属性吗?
我自然希望Nullable<>
的getter返回Value
的值,与null
返回的HasValue
类似。我也希望false
返回GetType
类型信息,或者Nullable<int>
或num is int?
都能正常工作。为什么不起作用?如何检查num is Nullable<int>
是可为空的类型?
创建实例不会对此进行任何更改:
num
幕后是什么?
答案 0 :(得分:7)
Nullable<T>
有一点编译器魔力,使得它出现好像是一个null
值。但是没有。基本上,由于Nullable<T>
是值类型,因此开头不能为null
。它的可空性确定是否有值。这意味着您可以调用HasValue
(这很重要,因为这是编译器在编写num == null
时插入的内容)和不依赖于值的其他方法。
关于一些具体点:
ToString
是一种实现,类似于在字符串连接中使用null
值将其转换为字符串时的工作方式,即产生空字符串。您也不希望ToString
扔过。GetHashCode
对于将Nullable<T>
作为字典中的关键字或放入哈希集中是必要的。它也不应抛出,因此它必须在没有值的情况下返回明智的信息。但是,如果没有值,则禁止访问该值。正如注释中的Zohar Peled和Marc Gravell ♦所注,这是调用GetType
时隐式发生的情况:
看起来编译器可以用
相比,它总是给出令人困惑的答案。nullableValue.GetType()
静默替换typeof(SomeT?)
似乎是合乎逻辑的,但这意味着与object obj = nullableValue; Type type = obj.GetType()
您希望它的工作原理类似,但是
obj.GetType()
将始终返回typeof(T)
(而不是typeof(T?)
)或抛出NullReferenceException
,因为T?
框T
或null
(您不能问null
是什么类型)
编译器专门处理的结构的映射更多地是以下内容:
num == null → !num.HasValue
num != null → num.HasValue
num = null → num = new Nullable<int>()
num = 5 → num = new Nullable<int>(5)
(int) num → num.Value
(object) num → (object) num.Value // if HasValue
→ (object) null // if !HasValue
对运算符提供了额外的支持,最重要的是将比较运算符与不可为空的T
进行比较,以及对诸如null
之类的潜在??
值进行运算的各种运算符,但这就是要点
答案 1 :(得分:0)
不是一个真正的答案,而只是一个注释。您写道:
我自然希望
Value
的getter返回null
的值
不! Nullable<T>
存在的根本原因是为了保护您无需先检查即可获取null
值。