我們在日常的開發任務中,經常遇到對不同的數據結構執行相同的操作,例如有一個方法傳入的參數可能是字元串也可能是數字,這樣的情況下,一般我們是直接傳入一個object類型的參數,以便於可以實現這樣的功能。例如以下代碼。 private static void Show(object a) { Conso ...
我們在日常的開發任務中,經常遇到對不同的數據結構執行相同的操作,例如有一個方法傳入的參數可能是字元串也可能是數字,這樣的情況下,一般我們是直接傳入一個object類型的參數,以便於可以實現這樣的功能。例如以下代碼。
private static void Show(object a)
{
Console.WriteLine(a.ToString());
}
這樣的代碼可是實現我們需要的功能,但是確定也很明顯:1、只是傳入一個object類型的參數,對於調用方來說,根本不知道應該傳入一個什麼類型的參數,很有可能以為參入參數的問題造成代碼運行失敗。2.object是一個引用類型,如果我們要處理的是一個值類型,那麼就會產生裝箱和拆箱的操作,頻繁的裝箱拆箱會對程式的性能造成極大的影響。在這樣的需求下,C#2.0引入了泛型的概念,用於提供通用的功能以及編譯時的類型安全。
一、泛型的定義
泛型的定義非常簡單,<T>即可<>尖括弧不能省略,T代表需要操作的具體類型,T不是固定的你可以使用任何有意義的符號代替。例如以下定義
private static void Show<TValue>(TValue a)
{
Console.WriteLine(a.ToString());//TValue代表需要操作的類型,需要註意的是TValue是類型而不是實例
}
泛型的定義可以放在方法上面,也可以放在整個類上面,放在方法上面那麼只有當前方法是泛型方法,而直接放在類上面,則是把整個類全部定義為了泛型類,類內部的任何方法再使用此泛型的時候都可以不用再定義,如果需要定義多個泛型參數,則使用逗號隔開所有的參數,例如
private static void Show<TKey,TValue>(TValue a)
{
Console.WriteLine(a.ToString());
}
二、泛型方法的使用
定義了泛型方法就要去使用它,假設定義瞭如下的泛型方法
private static TValue Show<TValue>(TValue a)
{
Console.WriteLine(a.ToString());
return a;
}
那麼應該怎麼調用他呢?
Show<string>("此坑已滿");
Show<int>(123);
在<>中使用需要操作的類型代替TValue這個符號
上面就是調用泛型方法的結果。
三、泛型約束
有時候我們需要我們的泛型參數滿足一定的條件,例如我們需要T繼承自IComparable介面,或者我們要求T不能是值類型,只能是引用類型這樣的需求,該怎樣滿足呢?很簡單,使用where即可,例如以下定義
//以下定義要求TValue必須是一個引用類型
private static TValue Show<TValue>(TValue a) where TValue:class
{
Console.WriteLine(a.ToString());
return a;
}
有了這樣的定義,如果我們在調用泛型方法的時候把TValue定義為了一個值類型,那麼VS的智能提示就會在編譯時報錯,這樣就提供了編譯時的類型安全。例如
如果是要求TValue要滿足多個要求的話,則使用逗號分開即可
private static TValue Show<TValue>(TValue a) where TValue:class,IComparable,new ()
{
Console.WriteLine(a.ToString());
return a;
}
下麵是常用的一些約束規則
- 要求必須是引用類型,where T:class
- 要求必須是值類型,where T:struct
- 約束中可以有多個介面,但只能有一個基類,因為類型繼承要求單基類繼承
- new ()要求T必須有一個無參構造函數,同時new()必須放在約束的最後,同時C#不支持約束帶參數的構造函數
其他更加詳細的規則請參考MSDN
四、C#中常見的泛型
泛型可以用在方法,類型,介面,委托等等對象上面,在C#中有很多已經定義好的泛型供我們直接使用,例如List<T>,Dictionary<TKey,TValue>,Func<T1,T2>,Action<T>等等。他們的使用方法,請參考MSDN或者自行百度,謝謝!