可空類型允許我們創建一個值類型變量並且可以標記爲有效或無效,這樣我們就可以有效的把值類型設置爲“null”,在處理數據庫和其他包含可能未賦值的元素的數據類型時,將null賦值給數值類型或布爾類型的功能特別有用,例如數據庫中的布爾類型字段可以存儲值true或false,或者該字段也可以未定義。
可空類型總是基於另外一個叫做基礎類型的已經被聲明的類型,可以從任何值類型創建可空類型,包括預定義的簡單類型,不能從引用類型或其他可空類型創建可空類型。不能在代碼中顯式聲明可空類型,只能聲明可空類型的變量,之後我們會看到,編譯器會使用泛型隱式地創建可空類型,創建可空類型的變量,只需要在變量聲明中的基礎類型的名字後面加一個問號。
static void Main(string[] args)
{
//a i b值都爲null
int? a = null;
int? i = new int?();
bool? b = new bool?();
int? myNInt = 100;
if (myNInt != null) //直接與null比較
Console.WriteLine(myNInt);
if(myNInt.HasValue) //通過檢查它的HasValue屬性
Console.WriteLine(myNInt);
}
可空類型與非可空類型之間的轉換
(1)非可空類型--->可空類型 爲隱式,不需要強制轉換
(2)可空類型--->非可空類型 需要顯式轉換
空接合運算符(??)
空接合運算符由倆個連續的問號組成,它允許我們在可空類型變量爲null時返回一個值給表達式,它有倆個操作數,第一個操作數是可空類型的變量,第二個是相同基礎類型的不可空值,在運行時,如果第一個操作數運算後爲null,那麼第二個操作數就會被返回爲運算符結果。簡單來講就是如果??左邊操作數爲null,則返回??右邊的操作數。
static void Main(string[] args)
{
int? i = null;
Console.WriteLine(i ?? -1); //-1
i = 4;
Console.WriteLine(i ?? -1); //4
}
可空用戶自定義類型
我們可以創建用戶自定義值類型的可空形式,它的主要問題是訪問封裝的基礎類型的成員,一個可空類型不直接暴露基礎類型的任何成員,例如struct的字段是公共的,它可以被結構的任何實例所訪問到,然而,結構的可空形式只通過Value屬性暴露基礎類型,它不直接暴露它的任何成員,儘管這些成員對結構來說是公共的,但是它們對可空類型來說不是公共的。
struct S
{
public int X;
public int Y;
public S(int xVal,int yVal)
{
X = xVal; Y = yVal;
}
}
static void Main(string[] args)
{
S? s = new S(5, 10);
S s1 = new S(6, 12);
Console.WriteLine("{0} {1}", s1.X, s1.Y); //非可空類型的訪問
Console.WriteLine("{0} {1}", s.Value.X, s.Value.Y); //可空類型的訪問
}
Nullable<T>
可空類型通過一個叫做Syatem.Nullable<T>的.NET類型來實現,它使用了C#的泛型特性,C#可空類型的問號語法是創建Nullable<T>類型變量的快捷語法,Nullable<T>接受了基礎類型並把它嵌入結構中,同時給結構提供可空類型的屬性、方法和構造函數。
public class Program
{
struct S
{
public int X;
public int Y;
public S(int xVal,int yVal)
{
X = xVal; Y = yVal;
}
}
static void Main(string[] args)
{
S? s = new S(5, 10);
Nullable<S> s1 = new Nullable<S>((S)s);
Console.WriteLine("{0} {1}", s.Value.X, s.Value.Y);
Console.WriteLine("{0} {1}", s1.Value.X, s1.Value.Y);
}
}