【问题标题】:Methods on Nullable typesNullable 类型的方法
【发布时间】:2019-02-05 18:55:47
【问题描述】:

有人可以解释为什么可以在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

我可以在调试模式下检查numnull,那么ToString 方法或HasValue getter 怎么可能在null 实例上被调用,但对于Value 和@ 987654330@不可能吗?它们都是Nullable<> 类型的方法或属性吗?

我自然希望Value getter 返回null 值,类似于HasValue 返回false。我也希望GetType 返回Nullable<int> 类型信息,或num is int?num is Nullable<int> 有效。为什么它不起作用?如何检查num 是否为可空类型?

创建一个实例并不会改变任何东西:

Nullable<int> num = new Nullable<int>();

幕后是什么?

【问题讨论】:

  • 从文档开始。 Nullable.ToString: "如果 HasValue 属性为真,则为当前 Nullable 对象的值的文本表示,如果 HasValue 属性为假,则为空字符串 ("")。"
  • Nullable&lt;T&gt; 是一个结构体,因此实际上不可能是null。这是编译器的特殊处理,使您能够首先执行int? num = null
  • 大部分是 stackoverflow.com/questions/12725631/… 的副本。它已经解释了为什么ToString 有效而GetType 抛出NullReferenceException 的核心问题

标签: c# nullable


【解决方案1】:

Nullable&lt;T&gt; 有一点编译器的魔力,使它显示就好像有一个null 值。但是没有。基本上,由于Nullable&lt;T&gt; 是一个值类型,它不能以null 开头。它的可空性取决于是否有值。这意味着您可以调用HasValue(这很重要,因为这是编译器在您编写num == null 时插入的内容)和其他不依赖于存在值的方法。

至于具体几点:

  • ToString 是一种实现,其工作方式类似于在字符串连接中使用 null 值转换为字符串的方式,即生成空字符串。你也不想让ToString 扔掉。
  • GetHashCode 有必要将 Nullable&lt;T&gt; 作为键放入字典中,或者将它们放入哈希集中。它也不应该抛出,所以它必须在没有价值时返回一些合理的东西。
  • documentation 解释了一些基本概念。

但是,当没有值时访问该值是被禁止的。正如 cmets 中的 Zohar PeledMarc Gravell ♦ 注释,这是在调用 GetType 时隐式发生的:

编译器可以默默地将nullableValue.GetType() 替换为typeof(SomeT?) 似乎是合乎逻辑的,但这意味着与

object obj = nullableValue;
Type type = obj.GetType()

您可能希望这会以类似方式工作,但obj.GetType() 将始终返回typeof(T)(而不是typeof(T?)),或者将NullReferenceException 抛出,因为T? 将框发送到T 或@987654346 @(你不能问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

还有对运算符的额外支持,最重要的是比较运算符与不可为空的Ts 以及各种适用于潜在null 值的运算符,例如??,但这就是要点。

【讨论】:

  • 要解决为什么GetType 返回空引用异常的问题,请阅读How to: Identify a nullable type (C# Programming Guide)。基本上,这是对null 的尝试。
  • 是的,装箱/拆箱的基本行为解释了这一点。谢谢,但是我仍然认为请求类型并获得空异常并不直观。
【解决方案2】:

不是真正的答案,只是一个注释。你写:

我自然希望 Value getter 返回 null

不! Nullable&lt;T&gt; 存在的真正原因是为了防止您在没有先检查的情况下获取 null 值。

【讨论】:

  • Value 是一个必须是值类型的T 也无济于事,所以它只是不能null
  • 另外,.Value 被输入为T,所以它根据定义永远不能返回null(因为你不能有Nullable&lt;Nullable&lt;T&gt;&gt;) ;值得注意的是,.GetValueOrDefault() 从未失败地返回
  • Joey:我想说的是,这正是 确实 提供帮助的事情,也是创建 Nullable&lt;T&gt; 的原因。
  • 我认为它的存在不是为了保护你,而是允许你在不能保存空值的类型上拥有空值(从 db 或 json 端点获取),但是是的,我改变了一点Value getter 的感知。基础值保存不能为空的原始值,因此通过 Value getter 读取值不能返回 null。这似乎合乎逻辑。
猜你喜欢
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多