内容简介:使用等等!除了本文提到的一些情况。注意看以下的代码。我们创建了一个值为
使用 Nullable<T>
我们可以为原本不可能为 null
的值类型像引用类型那样提供一个 null
值。不过注意: Nullable<T>
本身也是个 struct
,是个值类型哦。这意味着你随时可以调用 .HasValue
这样的方法,而不用担心会出现 NullReferenceException
。
等等!除了本文提到的一些情况。
Nullable
中的 null
注意看以下的代码。我们创建了一个值为 null
的 int?
,然后依次输出 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; }
结果是……
果是……
是……
……
…
崩掉了……
那么我们在 value
后面加个空传递运算符:
-- Console.WriteLine($"type = {value.GetType()}"); ++ Console.WriteLine($"type = {value?.GetType()}");
现在再次运行,我们确认了 value?.GetType()
的值为 null
;而 typeof(int?)
的类型为 Nullable<Int32>
。
然而,我们现在将 value
的值从 null
改为 1
:
-- int? value = GetValue(null); ++ int? value = GetValue(1);
竟然 value.GetType()
得到的类型是 Int32
。
于是我们可以得出结论:
- 对于可空值类型,当为
null
时,GetType()
会出现空引用异常; - 对于可空值类型,当不为
null
时,GetType()
返回的是对应的基础类型,而不是可空值类型; -
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
。
应该如何判断可空值类型的真实类型
使用 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; }
参考资料
- c# - Nullable type is not a nullable type? - Stack Overflow
- How to: Identify a nullable type - C# Programming Guide - Microsoft Docs
-
[Using nullable types - C# Programming Guide Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/nullable-types/using-nullable-types)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 类型混淆漏洞实例浅析
- Mysql基础语句+数据类型实例
- 从反序列化到类型混淆漏洞——记一次 ecshop 实例利用
- JVM指令分析实例三(方法调用、类实例)
- 通过实例入门Golang
- Iptables详解+实例
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。