.NET泛型初探
? 總所周知,.NET出現(xiàn)在.net framework 2.0,為什么要在2.0引入泛型那,因為微軟在開始開發(fā).net框架時并沒有想過多個類型參數(shù)傳輸時對方法的重構(gòu),這樣一來,開發(fā)人員就要面對傳輸多種類型的參數(shù)而不得以寫多個方法,但是,開發(fā)者的智慧是無限的,創(chuàng)造性也由此被挖掘出來,在泛型之前,便有開發(fā)者為了提到代碼利用率便想到使用object類型為參數(shù)類型來傳遞參數(shù),這無疑解決了多個類型的參數(shù)傳輸時并需要寫多個方法的問題。那么object類型為什么能實現(xiàn)接受多個不同類型的參數(shù)那?有了object類型還為什么要設(shè)計泛型那?object類型又有那么弊端那?其實有點(diǎn)基礎(chǔ)的開發(fā)人員應(yīng)該都知道object類型是所有類型的父類,通過里氏轉(zhuǎn)換原則我們知道所有父類出現(xiàn)的地方都可以用子類替換,這樣就可以接收多個參數(shù)了,同時因為object類型轉(zhuǎn)換裝拆箱對性能的影響,在2.0時,微軟推出了泛型。
??? ?下面,我們引入泛型的聲明和調(diào)用:
public static void Show<T>(T tParameter){
Console.WriteLine($"This is{typeof(GenericClass)}Show<T>,paratype={tParameter.GetType()},value={tParameter};
}
? ?打印的內(nèi)容我們沒必要關(guān)注,我們只看方法頭,我們可以看到方法頭和參數(shù)里面加了T這個字母,其實這就是泛型聲明的規(guī)則,泛型在聲明時,需要在方法頭加上<T>(T parm),
注意,尖括號里面的字母是可變的,可以是任何字母,但是尖括號里面的字母必須和參數(shù)里面的字母要一致,這樣一個方法就聲明好了。
? 下面我們接下來研究下泛型的調(diào)用過程,泛型是如何在未命名參數(shù)類型的情況下來聲明參數(shù)類型的,在下面程序入口我寫了兩個List的類型
class Program
? ? {
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? Console.WriteLine(typeof(List<int>));
? ? ? ? ? ? ? ? Console.WriteLine(typeof(List<string>));
??? 運(yùn)行我們發(fā)現(xiàn),TList雖然在調(diào)用時不知道傳的什么類型,但是加了占位符,那么占位符是什么那?我們從dos里面看到`1,對,這個就是占位符。那么定位符是在什么時候聲明的那?上代碼
class Program
? ? {
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int iParameter = 123;
? ? ? ? ? ? ? ? long lParameter = 456;
? ? ? ? ? ? ? ? string sParameter = "abc";
? ? ? ? ? ? ? ? object oParameter = "123456";
? ? ? ? ? ? ? ? Console.WriteLine("**********************");
? ? ? ? ? ? ? ? CommonClass.ShowInt(iParameter);
? ? ? ? ? ? ? ? CommonClass.ShowLong(lParameter);
? ? ? ? ? ? ? ? CommonClass.ShowString(sParameter);
? ? ? ? ? ? ? ? Console.WriteLine("**********************");
? ? ? ? ? ? ? ? CommonClass.ShowObject(oParameter);
? ? ? ? ? ? ? ? CommonClass.ShowObject(iParameter);
? ? ? ? ? ? ? ? CommonClass.ShowObject(lParameter);
? ? ? ? ? ? ? ? CommonClass.ShowObject(sParameter);
? ? ? ? ? ? ? ? Console.WriteLine("**********************");
? ? ? ? ? ? ? ? GenericClass.Show<object>(oParameter);
? ? ? ? ? ? ? ? GenericClass.Show<int>(iParameter);
? ? ? ? ? ? ? ? //GenericClass.Show<int>(lParameter);//指定類型必須和參數(shù)一致
? ? ? ? ? ? ? ? GenericClass.Show(iParameter);//不指定,由編譯器自動推算
? ? ? ? ? ? ? ? GenericClass.Show<long>(lParameter);
? ? ? ? ? ? ? ? GenericClass.Show<string>(sParameter);
? ? ? ? ? ? ? ? Console.WriteLine("**********************");
? ? ? ? ? ? ?}
? ? ? ? ? ? catch (Exception ex)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Console.WriteLine(ex.Message);
? ? ? ? ? ? }
? ? ? ? ? ? Console.Read();
? ? ? ? }
? ? }
}
? 這里我就不贅述了,直接說一下吧,其實泛型在聲明的時候不知道什么類型(用了占位符),是在調(diào)用的時候編譯器自動推算,也可以在調(diào)用時指定,這是一種延遲思想延遲聲明:把參數(shù)類型的聲明,延遲到調(diào)用的時候,推遲一切可以推遲的,這也是設(shè)計模式的一種思想。編譯以后的泛型和普通方法就一樣了,所以不會影響性能,可以想象成又一個重載
泛型的好處:一個方法支持多種參數(shù)類型?,性能無損耗。
泛型支持多個參數(shù)可想而知,但是真的無損耗嗎?不清楚,好,對一切我們要持一種懷疑的態(tài)度去看,科學(xué)的自然會被證實,那么這里我們測試一下。用到類:Stopwatch
long commonTime = 0;
? ? ? ? ? ? ? ? long objectTime = 0;
? ? ? ? ? ? ? ? long genericTime = 0;
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? Stopwatch watch = new Stopwatch();
? ? ? ? ? ? ? ? ? ? watch.Start();
? ? ? ? ? ? ? ? ? ? for (int i = 0; i < 100000000; i++)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? CommonClass.ShowObject(iParameter);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? watch.Stop();
? ? ? ? ? ? ? ? ? ? objectTime = watch.ElapsedMilliseconds;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? Stopwatch watch = new Stopwatch();
? ? ? ? ? ? ? ? ? ? watch.Start();
? ? ? ? ? ? ? ? ? ? for (int i = 0; i < 100000000; i++)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? CommonClass.ShowInt(iParameter);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? watch.Stop();
? ? ? ? ? ? ? ? ? ? commonTime = watch.ElapsedMilliseconds;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? Stopwatch watch = new Stopwatch();
? ? ? ? ? ? ? ? ? ? watch.Start();
? ? ? ? ? ? ? ? ? ? for (int i = 0; i < 100000000; i++)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? GenericClass.Show<int>(iParameter);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? watch.Stop();
? ? ? ? ? ? ? ? ? ? genericTime = watch.ElapsedMilliseconds;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? Console.WriteLine("commonTime={0}", commonTime);
? ? ? ? ? ? ? ? Console.WriteLine("objectTime={0}", objectTime);
? ? ? ? ? ? ? ? Console.WriteLine("genericTime={0}", genericTime);
里面的三個類分別是object類型和普通類以及泛型,分別對int、string以及實體類型的調(diào)用,我直接上答案:
??? 通過圖上給出的運(yùn)行時間,泛型是最快的,然后是普通方法,然后是object類型,大家要知道,我這是在運(yùn)行1億次的情況下的所得的結(jié)果,其實,我們還得出一個結(jié)論,那就是,object類型確實有性能影響,單并不罪大惡極,也不是不能用的,也要看程序所處的環(huán)境。
????補(bǔ)充一點(diǎn),泛型不是語法糖,語法糖是編譯器提供帶的功能,不要誤解了
原文地址: http://www.cnblogs.com/renzhitian/p/6202917.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注
總結(jié)
- 上一篇: 微软称开源.NET吸引了更多开发者
- 下一篇: 博客园官方 NuGet镜像上线试运行