C#笔记——可为空值/引用类型
本文最后更新于:2023年9月7日 下午
可为空值类型
基本概念
可为空值类型T?
表示其基础值类型T
的所有值及额外的null
值。比如bool?
的值有:true
、false
和null
,而普通的bool
的值只有:true
和false
,因为基础值类型T
本身不能是可为空的值类型。
任何可为空的值类型都是泛型System.Nullable<T>
结构的实例,比如int?
是System.Nullable<int>
的实例。
声明和赋值
声明就是基础值类型后加一个?
,赋值则跟基础值类型一样。
1 |
|
检查可为空值类型的实例
使用只读属性Nullable<T>.HasValue
来检查和获取可为空值类型变量的值:
1 |
|
从可为空的值类型转换为基础类型
如果要将可为空值类型的值分配给不可以为空的值类型变量,则可以使用Null合并操作符??
或者Nullable<T>.GetValueOrDefault(T)
方法(此方法若不传递参数则使用基础值类型的默认值来替代null
):
1 |
|
也可以使用显式强制转换为不可为空的类型(注意如果可为空的值类型的值为null
的话,显式强制转换将抛出InvaildOperationException
异常):
1 |
|
提升的运算符
预定义的一元运算符和二元运算符或值类型T
支持的任何重载运算符也受相应的可为空值类型T?
支持。只要有一个操作数为null
,那么运算的结果就是null
。这里的特殊例子是bool?
类型,详情可以参考官方文档。
1 |
|
对于比较运算符>
、>=
、<
、<=
,只要有一个操作数为null
,返回的结果就是false
。
对于相等运算符==
,如果两个操作数都为null
,则结果为true
;如果只有一个操作数为null
,则结果为false
。
对于不等运算符!=
,参考相等运算符==
。
装箱和取消装箱
给可为空的值类型的实例进行装箱操作,实质上是对基础值类型T
的对应值装箱:
- 如果
HasValue
返回false
,则生成空引用。 - 如果
HasValue
返回true
,则基础值类型T
的对应值将装箱,而不对Nullable<T>
的实例进行装箱。
如何确定可为空的值类型
下面的示例演示了如何确定System.Type
实例是否表示已构造的可为空值类型:
1 |
|
严格按照上面写就好了,先使用typeof
运算符获取System.type
实例,再使用Nullable.GetUnderlyingType
方法来检查。如果想知道为什么,简洁来说就是Object.GetType
方法获取到的Type
实例无法区分,is
运算符无法确定,详细的原因参考官方文档。
可为空引用类型
用来干什么?——用于降低代码导致运行时引发System.NullReferenceException
异常(尝试取消引用空对象引用时引发的异常)的可能性。
1 |
|
在可为null
的感知上下文中:
- 引用类型
T
的变量必须用非null
值进行初始化,并且不能为其分配可能为null
的值。 - 引用类型
T?
的变量可以用null
进行初始化,也可以分配null
,但在取消引用之前必须对照null
进行检查。 - 类型为
T?
的变量m
在应用null
包容运算符(!
)时被认为是非空的,如m!
。
限制
- 可为空的引用类型不能用作基类或实现的接口
- 可为空的引用类型不能用于任何对象创建
- 可为空的引用类型不能用于任何类型测试表达式
- 可为空的引用类型不能是成员访问表达式的类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14public MyClass : System.Object? // not allowed
{
}
var nullEmpty = System.String?.Empty; // Not allowed
var maybeObject = new object?(); // Not allowed
try
{
if (thing is string? nullableString) // not allowed
Console.WriteLine(nullableString);
} catch (Exception? e) // Not Allowed
{
Console.WriteLine("error");
}
希望本文章能够帮到您~