建议05: 使用int?来确保值类型也可以为null
基元类型为什么需要为null?考虑两个场景:
1)数据库中一个int字段可以被设置为null。在C#中,值被取出来后,为了将它赋值给int类型,不得不首先判断一下它是否为null。如果将null直接赋值给int类型,会引发异常。
2)在一个分布式系统中,服务器需要接收并解析来自于客户端的数据。一个int型数据可能在传输过程中丢失或被篡改了,转型失败后应该保存为null值,而不是提供一个初始值。
类似的场景还有很多,所以从.NET 2.0开始,FCL中提供了一个额外的类型:可以为空的类型Nullable<T>。它是一个结构体,声明如下:
[SerializableAttribute]
public struct Nullable<T> where T: struct
 
[Serializable, StructLayout(LayoutKind.Sequential), TypeDependency("System.Collections.Generic.NullableComparer`1"), TypeDependency("System.Collections.Generic.NullableEqualityComparer`1")] public struct Nullable<T> where T: struct { private bool hasValue; internal T value; public Nullable(T value) { this.value = value; this.hasValue = true; } public bool HasValue { get { return this.hasValue; } } public T Value { get { if (!this.HasValue) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue); } return this.value; } } public T GetValueOrDefault() { return this.value; } public T GetValueOrDefault(T defaultValue) { if (!this.HasValue) { return defaultValue; } return this.value; } public override bool Equals(object other) { if (!this.HasValue) { return (other == null); } if (other == null) { return false; } return this.value.Equals(other); } public override int GetHashCode() { if (!this.HasValue) { return 0; } return this.value.GetHashCode(); } public override string ToString() { if (!this.HasValue) { return ""; } return this.value.ToString(); } public static implicit operator T?(T value) { return new T?(value); } public static explicit operator T(T? value) { return value.Value; } }
因为是结构体,所以只有值引用类型才可以作为“可以为空的类型”(引用类型本身就可以为null)。一个可以为空的int类型表示为:
Nullable<int> i = null;
它也可以表示为:
int? i = null;
语法T?是Nullable<T>的简写,两者可以相互转换。可以为 null 的类型表示其基础值类型正常范围内的值再加上一个null值。例如,Nullable<Int32>,其值的范围为-2 147 483 648 ~ 2 147 483 647,再加上一个null值。
现在来看看可空类型和基元类型的互相转换。基元类型提供了其对应的可空类型的隐式转换,如下所示:
int? i = null;
int j = 0;
i = j;
反过来,可空类型不可隐式转换为对应的基元类型,正确的转换形式如下:
int? i = 123;
int j;
if(i.HasValue)
{
    j = i.Value;
}
else
{
    j = 0;
}
但是,这段代码看上去是不是有点烦琐?所以,在阐述可空类型的时候,不得不提到??运算符。??最大的用处就是将可空类型的值赋值给对应的基元类型进行简化,上文代码的一个简化形式就是:
int? i = 123;
int j = i ?? 0;
int j = i ?? 0;表示的意思是,如果i的HasValue为true,则将i的value赋值给j;否则,就给j赋值为0。
转自:《编写高质量代码改善C#程序的157个建议》陆敏技
以下是本书作者的相关信息,在此感谢作者的辛勤奉献!
原文作者:陆敏技
书名:编写高质量代码:改善C#程序的157个建议
作者Blog:www.cnblogs.com/luminji
 
                    
                 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号