Framework類庫中的泛型
泛型可以使代碼重用,提高開發效率
CLR允許在引用類型、值類型或接口中定義泛型方法;
CLR允許創建泛型引用類型、泛型值類型(枚舉不允許創建)、泛型委托類型和泛型接口類型;
System.Collections.Generics
中定義了List<T>
,<T>
表示它操作的是一個未指定數據類型;定義泛型類型或方法時,T
是一個變量名,在源代碼中能夠使用一個數據類型的任何位置都能用T
,例如方法參數、返回值等等。
泛型參數變量要么稱為T
,要么以T
開頭(如Tkey,TEvent...)
定義好泛型類型后,使用泛型類型或方法時,制定具體的類型實參
var validationResult = new List<ValidationResult>();
泛型的優勢
- 源代碼保護
使用泛型算法時候,不需要了解算法內部的具體實現 - 類型安全
將泛型算法運用于一個具體的類型,只有與數據類型兼容算法的對象才能使用算法,若不兼容,便會編譯錯誤或運行異常 - 更加清晰的代碼
由于編譯器強制類型安全,減少了代碼中的轉型次數 - 更佳的性能
由于裝箱會造成性能的浪費,通過泛型避免了裝箱
下面是一段泛型與非泛型的算法性能測試對比
class Program
{
static void Main(string[] args)
{
ValueTypePreTest();
ReferenceTypePreTest();
Console.ReadKey();
}
private static void ValueTypePreTest()
{
const int count = 10000000;
using (new OperationTimer("List<Int32>"))
{
List<int> l = new List<int>();
for (int i = 0; i < count; i++)
{
l.Add(i);
int x = l[i];
}
l = null;//確保進行垃圾回收
}
using (new OperationTimer("ArraryList of Int32"))
{
ArrayList arr = new ArrayList();
for (int i = 0; i < count; i++)
{
arr.Add(i);
int x = (int)arr[i];
}
arr = null;
}
}
private static void ReferenceTypePreTest()
{
const int count = 10000000;
using (new OperationTimer("List<String>"))
{
List<string> l = new List<string>();
for (int i = 0; i < count; i++)
{
l.Add("X");
string x = l[i];
}
l = null;//確保進行垃圾回收
}
using (new OperationTimer("ArraryList of String"))
{
ArrayList arr = new ArrayList();
for (int i = 0; i < count; i++)
{
arr.Add("X");
string x = (string)arr[i];
}
arr = null;
}
}
}
class OperationTimer : IDisposable
{
private long _start;
private string _text;
private int _collectionCount;
public OperationTimer(string text)
{
_text = text;
_collectionCount = GC.CollectionCount(0);
_start = Stopwatch.GetTimestamp();
}
public static void PreparForPeration()
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
public void Dispose()
{
Console.WriteLine("{0,6:###.00} seconds(GCs={1,3}) {2}",
(Stopwatch.GetTimestamp() - _start) / (double)Stopwatch.Frequency,
GC.CollectionCount(0) - _collectionCount,
_text
);
}
}
Wintellect的Power Collections庫
Wintellect公司開發的一些C++集合類庫
泛型基礎結構
開放類型和封閉類型
具有泛型類型參數的類型稱為開放類型(例如:Directory<,>
),CLR禁止構造開放類型的任何實例
代碼引用一個泛型類型時,可指定一組泛型類型實參,假如為所有類型實參傳遞都是實際數據類型,稱為封閉類型(例如:List<string>
)
開放類型和封閉類型
具有泛型類型參數的類型稱為開放類型(例如:Directory<,>
),CLR禁止構造開放類型的任何實例
代碼引用一個泛型類型時,可指定一組泛型類型實參,假如為所有類型實參傳遞都是實際數據類型,稱為封閉類型(例如:List<string>
)
泛型類型和繼承
泛型類型任然是一種類型,它可以從其他類型派生。
泛型類型的同一性
不要為了簡化代碼而定義一個新的類型繼承泛型,這樣會散失同一性和相等性,可以通過下面的方式簡化代碼輸入
using DateTimeList=System.Collections.Generic.List<DateTime>;
代碼爆炸
CLR 優化了泛型類型的編譯代碼,避免了每次都要為不同的泛型類型生成對應的代碼
泛型接口
通過泛型接口避免值類型發生裝箱
public interface IEnumerator<T>:IDisposable,IEnumerator
{
T Current{get;}
}
泛型委托
保證任何類型的對象都能以一種類型安全的方式傳給回調方法;而且泛型委托也是為了避免一個值類型實例在傳遞給回調方法時不再發生裝箱
委托和接口的協變和逆變泛型類型實參
泛型方法
泛型除了可以定義類型的參數,還可以為方法定義一個只作用域于方法的類型參數
泛型的類型推斷
public static void Display<T>(T input){
System.Console.WriteLine(input);
}
Display(123);
Display("aaa")
泛型和其他成員
在C#中,屬性、事件、索引器、構造函數等成員是不能有類型參數的,但是在泛型類型中,這些成員的代碼是可以使用類型參數的;
C#不允許他們指定自己的泛型類型參數,C#團隊認為開發人員很少需要將這些成員作為泛型使用,當然為這些成員添加泛型代價也很高
可驗證性和約束
文章列表