一、泛型T
這個T在實際使用中很常見,比如List<T>。其實我們還可以寫成List<object>。但是這樣寫會有一個問題。比如我把一個int數據存入到一個List<object>集合中,int則會被自動轉成object,當我們試圖取取用這個int數據的時候,我們還要把object轉成int。這期間有一個轉換,int=》object=》int,這個轉換涉及到拆箱和封箱操作,也就是引用類型到值類型或者值類型到引用過程轉換的過程,這個是很耗時的。當數據量大的時候,這個對於代碼的效率是有不可忽視的影響的。
同時,如果不小心把一個string類型存入到了這個List<object>中,系統是不會報錯的。但是當要取用的時候,你也許開始沒發現不小心存入了一個string類型,然后你想當然的認為它是一個int類型,把它轉成了int,這個時候你的程序就要報錯了。這也是一個問題。
這個時候使用List<object>的隱患就顯現出來了。為了比較好的解決這兩個問題,c#引入了T這個概念,因為在大部分場景下,我們的類型都是確定的,沒必要用object。
當我們使用List<T>的時候,我們首先實例化一個List<T>,比如這樣的代碼:
List<string> list=new List<string>();
這個代碼的意思是告訴list這個集合只能放string這個類型的數據,放其他類型的數據,編譯器是會報錯的。這樣我們不難理解,T這個東西的作用,其實就是一個通用的容器,制造它的人開始不指定它是用來裝什么的,而使用者在使用它的時候要告訴這個容器准備用來裝什么,容器知道了用來裝什么之后,后面所有存入操作,它都要檢查一下你放的東西是不是開始指定的東西類型。
二、泛型方法
現在有一個需求,需要寫一個方法,這個方法傳入的參數可能是int型的,也可能是string型的。首先我們可以用方法的重載方案解決這個問題,比如下面兩個重載方法:
public void test(int param)
{ }
public void test(string param)
{ }
但是這樣的話如果支持的類型變多了,那么你需要寫很多重載方法。如果只寫一個重載方法,則可以寫成
public void test(object param) { }
但是這樣寫又出現object轉成其他類型的問題,會帶來效率損失。同時不檢查類型,一旦傳入了不支持的類型,可能會出問題。
現在把test方法改造一下,這樣寫:
public void test<T>(T param){ }
這樣寫之后,使用的時候要求提前通知這個方法,你傳入的是什么類型,即:
test<int>(10);
如果寫成 test<int>("10");編譯器就會報錯。
這就是泛型方法。這里面我們省略了方法內部的實現,其實仔細想一下,如果要在這樣的方法里面添加業務代碼,似乎除了用於存放數據的集合之外,並沒有多少場景需要這么寫方法。沒錯,泛型這個東西最常用的應用場景就是數據集合。而List<T>就是一個存放各種數據的泛型類。
三、泛型類
上面的方法:public void test<T>(T param){ },我們可以嘗試一下把<T>去掉,只寫成public void test(T param){ }看看會發生什么。你會發現編譯器會報錯,那么我們再嘗試一下在這個方法的類名上加上<T>,即寫成:
class TClass<T>
{
public void test(T param)
{ }
}
你會發現,如果把<T>放到類名上,里面的方法就不需要加 <T>了,同時編譯器也不會報錯。這是一種比較簡潔的寫法。這個時候,TClass這個類就是泛型類,而它的構造方法,則和普通的類的構造方法的寫法是一樣的。當你要實例化這個類型的時候,必須告訴這個類型T代表哪個類型,之后,所有這個類里面被標識了T的地方,都是指你開始實例化指明的類型。比如test這個方法里面傳入的param,一定要和你開始實例化這個類的時候指明的類型一致。再比如你寫一個返回T的方法: public T returnTest() { },這個方法的返回值也必須是你實例化類時指明的類型。如果我們TClass改成List,把test改成Add,則方法變成了下面這樣
class List<T>
{
public void Add(T param)
{ }
}
這不就是我們經常用的List<T>這個泛型集合嗎。當然它的內部實現還有很多東西,這里我們不去關注。
四、有了泛型類的概念,泛型接口就很好理解了,給上面的TClass寫一個接口進行規范:
interface ITClass<T>
{
void test(T param);
}
上面講的TClass繼承這個接口就可以了:
class TClass<T> : ITClass<T>
{
public void test(T param)
{
throw new NotImplementedException();
}
}
————————————————
版權聲明:本文為CSDN博主「returnTrue999」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/dap769815768/article/details/81946506