为什么需要 Nullable<T>
- 例如,c#中的数字不可为空,而数据库中的数字可为空,这导致二者无法直接映射。
- 二者映射的解决方案,是将数字变为引用类型,但这会抹杀,值类型低系统开销,这一优点
泛型结构 Nullable<T>
Nullable<T>
定义了一个约束,T必须为结构,例如Int32就是一个结构
运算符重载
Nullable<T>
转换为T
,显式定义,需要强转(T)
T
转换为Nullable<T>
,隐式定义,因为它总能成功
public struct Nullable<T>
where T : struct
{
public Nullable(T value)
{
_hasValue = true;
_value = value;
}
private bool _hasValue;
public bool HasValue => _hasValue;
private T _value;
public T Value
{
get
{
if(!_hasValue)
{
throw new InvalidOperationException("no value");
}
return _value;
}
}
public static explicit operator T(Nullable<T> value) => _value.Value;
public static implicit operator Nullable<T>(T value) =>
new Nullable<T>(value);
public override string ToString() => !HasValue? string.Empty : _value.ToString();
}
Nullable<T>
的使用
Nullable<int> x;
//将Nullable<int> 当做int来使用
x = 4;
x += 3;
//当做可空int来使用前,要判断一下
if(x.HasValue)
{
int y = x.Value;
}
//可以为空
x = null;
?
运算符 定义 可空类型
由于
Nullable<T>
使用频繁, 因此C#提供了一个运算符?
定义可空类型
//一样的效果
Nullable<int> x1;
int? x2;
可空类型可以与
null
,进行比较
//x是int?
if(x == null)
{
//...
}
else if(x < 0)
{
//...
}
两个可空类型的变量做算术运算,只要有一个是
null
,其结果就是null
// x1, x2均为 int?
int? x3 = x1 + x2;
从非可空类型转换为可空类型时,隐式转换就行,总是成功的
int y1 = 4;
int? x = y1; //隐式转换,总是成功
从可空类型转换为非可空类型时,需要显式转换,当值为
null
时,会抛出InvalidOperationException
// x1 为 int?
int y1 = (int)x1; //需要 类型强制转换运算符,来进行显式转换
从可空类型转换为非可空类型时,可以不用显式转换,而是用合并运算符
??
, 为转换定义一个默认值
// x1 为 int?, 如果x1是null, 就转而使用0
int y1 = x1 ?? 0;