前言:
问:为什么会有可空值类型的诞生?
答:应对在某些特定场景中获取的信息可能是不完整的。
C# 1中的可空值类型
在C#1中没有对应的表示Null值的方法。当时普遍都是采用其他方式。第一种在数据缺失的情况下给其一个默认值。第二种是采用一个标识符来表示当前的数据是否有值。无论是哪种方式都会对我们的维护和多余的逻辑重复。
C# 2中的可空值类型
可空值类型定义如下所示:
在早期结构体的定义就是通过Nullable<T>T为我们需要传递的类型实参。T在结构体当中我门称呼为基础类型。如当前Nullable<int>结构体的基础类型是int。
举个例子:
Nullable<double> myNullable = new Nullable<double>();
提示:1 结构体会隐藏一个默认公共无参的构造器(结构体的共性) 2 结构体中的类型形参只支持值类型。(约束为 Struct的原因)如(int、double、decimal、long、float)
访问可空值类型
static void Main()
{
System.Nullable<int> myStruct = new System.Nullable<int>();
//myStruct = 10;
//HasValue: 指可空值类型中是否具有实际有效的值
if (myStruct.HasValue)
{
// Value:指可空值类型结构中实际的值
System.Console.WriteLine(myStruct.Value);
}
else
{
throw new System.Exception();
}
System.Console.ReadLine();
}
可空值类型提供的方法
无参的方法GetValueOrDefault
static void Main()
{
System.Nullable<decimal> myStruct = new System.Nullable<decimal>();
myStruct = 10;
//输出10
System.Console.WriteLine(myStruct.GetValueOrDefault());
System.Nullable<decimal> myStruct2 = new System.Nullable<decimal>();
//输出基础类型的默认值
//输出0 与 typeof(decimal)效果一致
System.Console.WriteLine(myStruct2.GetValueOrDefault());
System.Console.ReadLine();
}
示例解释:
当前的方法效果是当属性HasValue为true的时候是代表当前结构体是有实际值的情况下那么返回的就是当前结构体实际值,如果为false那么则返回当前实际结构体的基础类型的默认值 。
有参的方法GetValueOrDefault
System.Console.WriteLine(myStruct.GetValueOrDefault(45));
示例解释:
与上面一个无参的重载函数区别在于,当结构体并没有实际值的情况下那么返回的就是当前您传入的值。当结构体具有实际值的情况下那么返回的则是实际值。
重写的Equals方法
public override bool Equals(object other)
{
if (!hasValue)
{
return other == null;
}
if (other == null)
{
return false;
}
return value.Equals(other);
}
示例解释:当结构体与被比较的object类型的数据都不为null的情况下再进行比较
可空值类型与基础类型的转换
System.Nullable<int> myStruct = new System.Nullable<int>();
//可以隐式执行基础类型与 Nullable<int> 的转化
int ints = 0;
myStruct = ints;
//显示转换 则相反
int intss = (int)myStruct;
注意:在显示转换中如果可空值类型结构体没有值,则是默认值的情况下会抛出异常,因为当前的默认值将会是Null,null是无法赋值给非空的值类型的。
装箱行为
装箱行为在可空类型与非可空类型是不同的,其中非可空类型被装箱时返回的结果类型就是原始的装箱类型,而可空类型发返回类型需要由 HasValue属性来决定,当HasValue为False时那么当前的非可空类型的引用则是Null 引用,为True时才是装箱时对应的数据类型的引用。
举个例子:
int X = default;
object o = X;
Console.WriteLine(typeof(int) == o.GetType());
Console.ReadLine();
示例解释:当前是非可空类型int 装箱到 object 类型中,返回的结果类型就是原始的装箱类型
//没有实际值
Nullable<int> @int = default;
object obj = @int;
Console.WriteLine(obj == null);
//具有实际值
Nullable<int> @int2 = 1;
object obj2 = @int2;
Console.WriteLine(obj2 == null);
Console.ReadLine();
示例解释:将可空类型装箱,运行将会报错
简化可空值类型特性
C# 提供了 Nullable<T>
结构,允许值类型具有 null
值。通过使用 ?
后缀,可以创建可空版本的值类型。例如,int?
是一个可空的 int
类型。(按照编码习惯使用,或者按照项目编码习惯,二者编译的效果相同 产生IL的代码是一致的)