在c#中,值对象是没有办法赋值为null
的。比如说,你想要定义一个布尔值,你的赋值数据要么得是true
、要么就得是false
,默认情况下我们永远没可能给这个布尔赋值为null
,即使只是对这个变量进行声明而不初始化数据,c#编译器也会给他在声明的同时赋予默认的初始化数据。布尔的初始化数据为false
,整数、浮点数为0。
不过,在实际工作中,我们难免会遇到需要给值类型对象赋值为null
的情况。比如说,我们在数据库有个客户列表,保存了客户的姓名、电话、出生日期等数据,而出生日期不是必选项,所以,在数据库中有可能存在客户没有留下生日的情况。
出生日我们需要使用DateTime
类型来处理,但是DateTime
类型在c#中是值类型对象(struct),没有办法赋值为null
。所以,对于没有出生日期的情况,反应在代码中我们就需要给DateTime
做一些特殊处理,让他可以赋值为null
了。
C#为类似上述情况提供的专门进行空处理的可空类型Nullable
,位于system命名空间中。
可空类型的创建:
Nullable
的使用方式很简单,以DateTime
为例,在Nullable
后面加上箭头括号,泛型为DateTime
。现在,我们的date变量就可以被设置为null
了。
Nullable<DateTime> date = null;
因为可控类型很常用,因此c#还很贴心得给这种类型设计了独特的语法接口,通过语法糖来简化代码。
DateTime? date = null;
bool HasValue
:Nullable
类型的属性成员,用于判断是否为空。
T Value
:Nullable
类型的属性成员,返回承载当前值的对应类型对象,如果为null
则抛出异常。
T GetValueOrDefault()
:Nullable
类型的方法成员,当为null
时,返回承载默认值的对应类型对象,当不为null
时候,返回承载当前值的对应类型对象。
class Program
{
static void Main(string[] args)
{
DateTime? date = null;
Console.WriteLine(date.GetValueOrDefault());
date = new DateTime(2022, 1, 2);
if (date.HasValue)
{
Console.WriteLine(date.Value);
}
}
}
注意:不能把一个Nullable
的Datetime
直接赋值给普通的Datetime
,因为他们两者的类型是截然不同的,c#编译器不知道应该怎么处理这种情况。
现在假设有一个需求,打印Nullable<DateTime>
变量date的日期,但有个要求,就是只有date有数据的时候,才显示date的日期;否则显示今天的日期。如果不使用合并运算符,一般会写成如下代码:
static void Main(string[] args)
{
DateTime? date = null;
if (date != null)
{
Console.WriteLine(date.GetValueOrDefault());
}
else
{
Console.WriteLine(DateTime.Today);
}
}
在实际工作中,我们有大量的代码都需要做类似的处理,先进行非空判断,然后再执行逻辑。不过,这坨代码其实很啰嗦,对于可空数据的处理,c#提供了一个非常强大的语法结构进行处理,就是连续使用两个问号,即合并运算符??
。
语法:变量a ?? 变量b/表达式
连续两个问号是Coalescing Operator,中文叫做合并运算。这是一个逻辑操作符,当左侧的变量为null
时,他将会返回合并操作符右侧数据,否则合并操作将会提取左侧的变量的真实数据,并且返回这个数据。于是,上面的代码就可以简写为:
static void Main(string[] args)
{
DateTime? date = null;
var result = date ?? DateTime.Today;
Console.WriteLine(result);
}