泛型是指一般形式,而不是特定形式。在C#中,泛型意味著不特定于特定數(shù)據(jù)類型。
C#允許您使用 type 參數(shù)并且不使用特定數(shù)據(jù)類型來定義泛型類,接口,抽象類,字段,方法,靜態(tài)方法,屬性,事件,委托和運算符。類型參數(shù)是在創(chuàng)建泛型類型的實例時指定的特定類型的占位符。
通過在類型名稱后的尖括號中指定類型參數(shù)來聲明泛型,例如 TypeName<T>,這里 T 是類型參數(shù)。
泛型類是在類名稱后的尖括號中使用類型參數(shù)定義的。下面定義了一個泛型類。
class DataStore<T> { public T Data { get; set; } }
上面,DataStore 是一個泛型類。T 稱為類型參數(shù),可用作 DataStore 類中的字段、屬性、方法參數(shù)、返回類型和DataStore類中的委托的類型。例如,Data 是泛型屬性,因為我們使用了類型參數(shù) T 作為其類型,而不是特定的數(shù)據(jù)類型。
您還可以定義多個類型參數(shù),并用逗號分隔。
class KeyValuePair<TKey, TValue> { public TKey Key { get; set; } public TValue Value { get; set; } }
您可以通過在尖括號中指定實際類型來創(chuàng)建泛型類的實例。下面創(chuàng)建泛型類的實例DataStore。
DataStore<string> store = new DataStore<string>();
上面,我們string在創(chuàng)建實例時在尖括號中指定了類型。因此,T將在編譯時將其替換為在整個類中使用的string任何類型T。因此,Data屬性的類型為string。
下圖說明了泛型的工作方式。
您可以為Data屬性分配一個字符串值。嘗試分配除字符串以外的其他值將導(dǎo)致編譯時錯誤。
DataStore<string> store = new DataStore<string>(); store.Data = "Hello World!";//obj.Data = 123; //編譯時錯誤
您可以為不同的對象指定不同的數(shù)據(jù)類型,如下所示。
DataStore<string> strStore = new DataStore<string>(); strStore.Data = "Hello World!"; //strStore.Data = 123; // 編譯時錯誤 DataStore<int> intStore = new DataStore<int>(); intStore.Data = 100; //intStore.Data = "Hello World!"; // 編譯時錯誤 KeyValuePair<int, string> kvp1 = new KeyValuePair<int, string>(); kvp1.Key = 100; kvp1.Value = "Hundred"; KeyValuePair<string, string> kvp2 = new KeyValuePair<string, string>(); kvp2.Key = "IT"; kvp2.Value = "Information Technology";
泛型類增加了可重用性。類型越多,可重用性就越高。然而,過多的泛化會使代碼難以理解和維護(hù)。
泛型類可以是其他泛型或非泛型類或抽象類的基類。
泛型類可以派生自其他泛型或非泛型接口,類或抽象類。
泛型類可以包含泛型字段。但是,無法初始化。
class DataStore<T> { public T data; }
下面聲明一個泛型數(shù)組。
class DataStore<T> { public T[] data = new T[10]; }
使用類型參數(shù)聲明其返回類型或參數(shù)的方法稱為泛型方法。
class DataStore<T> { private T[] _data = new T[10]; public void AddOrUpdate(int index, T item) { if(index >= 0 && index < 10) _data[index] = item; } public T GetData(int index) { if(index >= 0 && index < 10) return _data[index]; else return default(T); } }
上面的 AddorUpdate() 和 GetData() 方法是泛型方法。item參數(shù)的實際數(shù)據(jù)類型將在實例化 DataStore<T> 類時指定,如下所示。
DataStore<string> cities = new DataStore<string>(); cities.AddOrUpdate(0, "Mumbai"); cities.AddOrUpdate(1, "Chicago"); cities.AddOrUpdate(2, "London"); DataStore<int> empIds = new DataStore<int>(); empIds.AddOrUpdate(0, 50); empIds.AddOrUpdate(1, 65); empIds.AddOrUpdate(2, 89);
泛型參數(shù)類型可以與帶有或不帶有非泛型參數(shù)和返回類型的多個參數(shù)一起使用。以下是有效的泛型方法重載。
public void AddOrUpdate(int index, T data) { } public void AddOrUpdate(T data1, T data2) { } public void AddOrUpdate<U>(T data1, U data2) { } public void AddOrUpdate(T data) { }
通過在尖括號中使用方法名稱指定類型參數(shù),非泛型類可以包含泛型方法,如下所示。
class Printer { public void Print<T>(T data) { Console.WriteLine(data); } } Printer printer = new Printer(); printer.Print<int>(100); printer.Print(200); // 根據(jù)指定的值推斷 printer.Print<string>("Hello"); printer.Print("World!"); // 根據(jù)指定的值推斷
泛型提高了代碼的復(fù)用性。您無需編寫代碼來處理不同的數(shù)據(jù)類型。
泛型是類型安全的。如果嘗試使用與定義中指定的數(shù)據(jù)類型不同的數(shù)據(jù)類型,則會出現(xiàn)編譯時錯誤。
泛型具有性能優(yōu)勢,因為它消除了裝箱和拆箱的可能性。