轉載請註明出處:
http://hi.baidu.com/try__again/modify/blog/45bc5845c6db642bcffca39e
沒有值的時候怎麼辦?
對於一個引用類型的變量來說,其值是一個引用。而值類型變量的值是真正的值本身。對於引用類型來說,null是一個特殊的值,它表示“該引用變量沒有引用任何對象”。但是,它並不是一個有效的值類型的值。這非常容易理解,因爲如果C#設計者將null設計爲值類型的有效位,那麼勢必將增加內存開銷。
在C#1中,表示空值的值類型變量往往有如下幾種模式:
1、魔值,也就是說,犧牲一個值來表示空值。
2、引用類型包裝,它有兩種類型:直接利用object作爲變量類型,並根據需要進行裝箱和拆箱操作;對於一個可空值類型,爲其準備一個引用類型。
3、額外的bool標記
System,Nullable<T>:
該類型是可空類型的核心結構。它是一個泛型類型,且類型參數T存在一個值類型約束,T稱爲可空類型的基礎類型。它最重要的兩個屬性是HasValue和Value,前者是一個bool類型,它指出是否存在一個真正的值,後者則描述一個真正的值。
成員函數的調用:
using System;
using System.Collections.Generic;
using System.Text;
namespace CS_TEST
{
class Program
{
static void Display(Nullable<int> x)
{
Console.WriteLine("HasValue:{0}", x.HasValue);
if (x.HasValue)
{
Console.WriteLine("Value:{0}", x.Value);
Console.WriteLine("Explicit conversion:{0}", (int)x);
}
Console.WriteLine("GetValueOrDefault():{0}", x.GetValueOrDefault());
Console.WriteLine("GetValueOrDefault(10):{0}", x.GetValueOrDefault(10));
Console.WriteLine("ToString():\"{0}\"", x.ToString());
Console.WriteLine("GetHashCode();{0}", x.GetHashCode());
Console.WriteLine();
}
static void Main(string[] args)
{
Nullable<int> x = 5;
x = new Nullable<int>(5);
Console.WriteLine("Instance with value:");
Display(x);
Nullable<int> y = new Nullable<int>();
Console.WriteLine("Instance with value:");
Display(y);
Console.ReadLine();
}
}
}
Nullable:
這個類可以輔助泛型可空類型做一些事情,它只包含靜態方法,不能創建實例。
3個靜態方法:
public static int Compare<T>(Nullable<T> n1, Nullable<T> n2)public static bool Equals<T>(Nullable<T> n1, Nullable<T> n2)
第三個方法不是泛型方法:
public static Type GetUnderlyingType<Type nullbaleType>
如果第三個方法的參數是一個可空類型,那麼返回它的基礎類型,否則返回null。
C#2提供給可空類型的語法:
?修飾符:T? 等價於 Nullable<T>,用法完全一樣,只是語法不同,舉例如下:
int? nullable = 5;//定義可空類型
object boxed = nullable;//裝箱
Console.WriteLine(nullable.GetType());
int normal = (int)boxed;//拆箱成基礎類型
Console.WriteLine(normal);
nullable = (int?)boxed;//拆箱成可空類型
Console.WriteLine(nullable);
nullable = new int?();//將可空類型變量初始化爲空值
boxed = nullable;//裝箱
Console.WriteLine(boxed==null);
nullable = (int?)boxed;//拆箱成可空類型
Console.WriteLine(nullable.HasValue);
//將空值可空類型拆箱成基礎類型,將拋出異常
normal = (int)boxed;//拆箱成基礎類型
Console.WriteLine(normal);
使用null進行賦值和比較:
C#允許使用null在比較和賦值中表示一個可空類型的空值,就跟引用類型一樣。
值得注意的一個地方:
DataTime? death;
DataTime birth;
求壽命的方法:
public TimeSpan Age
{
get
{
if (death == null) return DataTime.Now - birth;
return death.Value - birth;
}
}
此外,null可以作爲參數進行傳遞,代表一個空值可空類型變量
思考:爲什麼在最後一行代碼中要使用death.Value - birth而非death - birth?
可空類型轉換:
null 到 T?的隱式轉換
T 到 T?的隱式轉換
T?到 T 的顯式轉換
S? 到 T?的轉換(顯式隱式皆可)
S 到 T?的轉換
S?到 T的顯示轉換
需要注意的是,如果S?是空值,那麼S?-->T的顯示類型轉換會拋出一個異常。
可空類型操作符的提升:略
提幾個比較值得注意的地方:
對於比較操作符,(null == null) == true,其它含有null的比較均爲false;
對於一元或者二元運算,如果有一個操作數爲null,那麼運算的結果也是一個null,即空值。
可空邏輯:
bool? a, b;
此時可空布爾類型有三種值,true, false, null。
此時布爾表達式的值取決於,如果空值的取值對布爾表達式的值有影響,那麼布爾表達式的值爲null。布爾表達式的值爲確定的布爾表達式的值。
空接合操作符:??
對於表達式:first??second
(1) 求first的值
(2) 如果first的值非空,那麼first的值就爲表達式的值
(3) 否則表達式的值爲second的值
因此,如前所述的代碼:
if (death == null) return DataTime.Now - birth;
return death.Value - birth;
可以寫成:
return (death??DataTime.Now) - birth;
現在回答一下前面紅色標註的問題:
若使用death - birth,其結果是一個DataTime?,因爲從T到T?存在一個隱式類型轉換,而反過來的轉換澤必定是顯式的。直接使用death肯定是可以的,但是需要作者對返回的結果再進行處理。