int? 竟然真的可以是 null!.NET/C# 确定可空值类型 Nullable<T> 实例的真实类型

栏目: ASP.NET · 发布时间: 6年前

内容简介:使用等等!除了本文提到的一些情况。注意看以下的代码。我们创建了一个值为

使用 Nullable<T> 我们可以为原本不可能为 null 的值类型像引用类型那样提供一个 null 值。不过注意: Nullable<T> 本身也是个 struct ,是个值类型哦。这意味着你随时可以调用 .HasValue 这样的方法,而不用担心会出现 NullReferenceException

等等!除了本文提到的一些情况。

Nullable 中的 null

注意看以下的代码。我们创建了一个值为 nullint? ,然后依次输出 value 的值、 value.GetType()

你觉得可以得到什么结果呢?

public class Program
{
    public static void Main(string[] args)
    {
        int? value = GetValue(null);

        Console.WriteLine($"value = {value}");
        Console.WriteLine($"type  = {value.GetType()}");
        Console.WriteLine($"TYPE  = {typeof(int?)}");

        Console.ReadLine();
    }

    private static int? GetValue(int? source) => source;
}

结果是……

果是……

是……

……

崩掉了……

int? 竟然真的可以是 null!.NET/C# 确定可空值类型 Nullable<T> 实例的真实类型

那么我们在 value 后面加个空传递运算符:

--  Console.WriteLine($"type  = {value.GetType()}");
++  Console.WriteLine($"type  = {value?.GetType()}");

现在再次运行,我们确认了 value?.GetType() 的值为 null ;而 typeof(int?) 的类型为 Nullable<Int32>

int? 竟然真的可以是 null!.NET/C# 确定可空值类型 Nullable<T> 实例的真实类型

然而,我们现在将 value 的值从 null 改为 1

--  int? value = GetValue(null);
++  int? value = GetValue(1);

竟然 value.GetType() 得到的类型是 Int32

int? 竟然真的可以是 null!.NET/C# 确定可空值类型 Nullable<T> 实例的真实类型

于是我们可以得出结论:

  1. 对于可空值类型,当为 null 时, GetType() 会出现空引用异常;
  2. 对于可空值类型,当不为 null 时, GetType() 返回的是对应的基础类型,而不是可空值类型;
  3. typeof(int?) 能够得到可空值类型。

Object.GetType() 和 is 对 Nullable 的作用

docs.microsoft.com 中,有一段对此的描述:

When you call the Object.GetType method on an instance of a nullable type, the instance is boxed to Object . As boxing of a non-null instance of a nullable type is equivalent to boxing of a value of the underlying type, GetType returns a Type object that represents the underlying type of a nullable type.

意思是说,当你对一个可空值类型 Nullable<T> 调用 Object.GetType() 方法的时候,这个实例会被装箱,会被隐式转换为一个 object 对象。然而对可空值类型的装箱与对值类型本身的装箱是同样的操作,所以调用 GetType() 的时候都是返回这个对象对应的实际基础类型。例如对一个 int? 进行装箱和对 int 装箱得到的 object 对象是一样的,于是 GetType() 实际上是不能区分这两种情况的。

那什么样的装箱会使得两个不同的类型被装箱为同一个了呢?

另一篇文档 描述了 Nullable<T> 装箱的过程:

  • If HasValue returns false, the null reference is produced.
  • If HasValue returns true, a value of the underlying value type T is boxed, not the instance of Nullable .
  • 如果 HasValue 返回 false ,那么就装箱一个 null
  • 如果 HasValue 返回 true ,那么就将 Nullable<T> 中的 T 进行装箱,而不是 Nullable<T> 的实例。

这才是为什么 GetType() 会得到以上结果的原因。

同样的,也不能使用 is 运算符来确定这个类型到底是不是可空值类型:

Console.WriteLine($"value is int  = {value is int}");
Console.WriteLine($"value is int? = {value is int?}");

最终得到两者都是 True

int? 竟然真的可以是 null!.NET/C# 确定可空值类型 Nullable<T> 实例的真实类型

应该如何判断可空值类型的真实类型

使用 Nullable.GetUnderlyingType(type) 方法,能够得到一个可空值类型中的基础类型,也就是得到 Nullable<T>T 的类型。如果得不到就返回 null

所以使用以下方法可以判断 type 的真实类型。

bool IsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;

然而,这个 type 的实例怎么来呢?根据前面的示例代码,我们又不能调用 GetType() 方法。

实际上,这个 type 的实例就是拿不到,在运行时是不能确定的。我们只能在编译时确定,就像下面这样:

bool IsOfNullableType<T>(T _) => Nullable.GetUnderlyingType(typeof(T)) != null;

如果你是运行时拿到的可空值类型的实例,那么实际上此方法也是无能为力的。

public class Program
{
    public static void Main(string[] args)
    {
        Console.Title = "walterlv's demo";

        int? value = GetValue(1);
        object o = value;
        Console.WriteLine($"value is nullable? {IsOfNullableType(value)}");
        Console.WriteLine($"o     is nullable? {IsOfNullableType(o)}");

        Console.ReadLine();
    }

    private static int? GetValue(int? source) => source;

    static bool IsOfNullableType<T>(T _) => Nullable.GetUnderlyingType(typeof(T)) != null;
}

int? 竟然真的可以是 null!.NET/C# 确定可空值类型 Nullable<T> 实例的真实类型

参考资料


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Sass and Compass in Action

Sass and Compass in Action

Wynn Netherland、Nathan Weizenbaum、Chris Eppstein、Brandon Mathis / Manning Publications / 2013-8-2 / USD 44.99

Written by Sass and Compass creators * Complete Sass language reference * Covers prominent Compass community plug-ins * Innovative approach to creating stylesheets Cascading Style Sheets paint the we......一起来看看 《Sass and Compass in Action》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具