這篇文章主要介紹了.net中泛型的概述與分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
在法庫等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計、做網(wǎng)站、成都外貿(mào)網(wǎng)站建設(shè)公司 網(wǎng)站設(shè)計制作按需網(wǎng)站開發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),全網(wǎng)營銷推廣,外貿(mào)營銷網(wǎng)站建設(shè),法庫網(wǎng)站建設(shè)費用合理。
泛型類和泛型方法兼復(fù)用性、類型安全和高效率于一身,是與之對應(yīng)的非泛型的類和方法所不及。泛型廣泛用于容器(collections)和對容器操作的方法中。.NET Framework 2.0的類庫提供一個新的命名空間System.Collections.Generic,其中包含了一些新的基于泛型的容器類。
泛型的可變類型參數(shù):通常用T,但也可以用任意非關(guān)鍵字和保留字;
所有的可變類型T在編譯時,都采用占位符的形式,在運行時將由實際傳入的類型來替換的所有的點位符;
針對早期版本的通用語言運行時和C#語言的局限,泛型提供了一個解決方案。以前類型的泛化(generalization)是靠類型與全局基類System.Object的相互轉(zhuǎn)換來實現(xiàn)。 .NET Framework 基礎(chǔ)類庫的ArrayList容器類,就是這種局限的一個例子。ArrayList是一個很方便的容器類,使用中無需更改就可以存儲任何引用類型或值類型。
ArrayList list = new ArrayList(); double sum = 0; |
缺點:
便利是有代價的,這需要把任何一個加入ArrayList的引用類型或值類型都隱式地向上轉(zhuǎn)換成System.Object。如果這些元素是值類型,那么當加入到列表中時,它們必須被裝箱;當重新取回它們時,要拆箱。類型轉(zhuǎn)換和裝箱、拆箱的操作都降低了性能;在必須迭代(iterate)大容器的情況下,裝箱和拆箱的影響可能十分顯著。另一個局限是缺乏編譯時的類型檢查,當一個ArrayList把任何類型都轉(zhuǎn)換為Object,就無法在編譯時預(yù)防客戶代碼中類似sum+=vlaue這樣的錯誤;
在System.Collections.Generic命名空間中的泛型List
List double sum = 0; |
與ArrayList相比,在客戶代碼中唯一增加的List
泛型類型或泛型方法的定義中,類型參數(shù)是一個占位符(placeholder),通常為一個大寫字母(也可以使用任意非關(guān)鍵字和保留字的名字),如T。在客戶代碼聲明、實例化該類型的變量時,把T替換為客戶代碼所指定的數(shù)據(jù)類型。泛型類,如泛型中給出的List
List |
泛型提供了下列五種約束:
約束 | 描述 |
where T : struct | 參數(shù)類型必須為值類型 |
where T : class | 參數(shù)類型必須為引用類型 |
where T : new() | 參數(shù)類型必須有一個公有的無參構(gòu)造函數(shù)。當與其它約束聯(lián)合使用時,new()約束必須放在最后。 |
where T : | 參數(shù)類型必須為指定的基類型或派生自指定基類型的子類 |
where T : | 參數(shù)類型必須為指定的接口或指定接口的實現(xiàn)??芍付ǘ鄠€接口的約束。接口約束也可以是泛型的。 |
無限制類型參數(shù):
不能使用!=和==對可變類型的實例進行比較,因為無法保證具體的類型參數(shù)支持這些運算符;
它們可以與System.Object相互轉(zhuǎn)換,也可顯式地轉(zhuǎn)換成任何接口類型;
可以與null比較。如果一個無限制類型參數(shù)與null比較,當此類型參數(shù)為值類型時,比較的結(jié)果總為false。
無類型約束:當約束是一個泛型類型參數(shù)時,它就叫無類型約束(Naked type constraints)。
class List |
在上面的示例中, Add方法的上下文中的T,就是一個無類型約束;而List類的上下文中的T,則是一個無限制類型參數(shù)。
無類型約束也可以用在泛型類的定義中。注意,無類型約束一定也要和其它類型參數(shù)一起在尖括號中聲明:
//naked type constraint
public class MyClass
因為編譯器只認為無類型約束是從System.Object繼承而來,所以帶有無類型約束的泛型類的用途十分有限。當你希望強制兩個類型參數(shù)具有繼承關(guān)系時,可對泛型類使用無類型約束。
泛型類封裝了不針對任何特定數(shù)據(jù)類型的操作。泛型類常用于容器類,如鏈表、哈希表、棧、隊列、樹等等。這些類中的操作,如對容器添加、刪除元素,不論所存儲的數(shù)據(jù)是何種類型,都執(zhí)行幾乎同樣的操作。
通常,從一個已有的具體類來創(chuàng)建泛型類,并每次把一個類型改為類型參數(shù),直至達到一般性和可用性的最佳平衡。當創(chuàng)建你自己的泛型類時,需要重點考慮的事項有:
哪些類型應(yīng)泛化為類型參數(shù)。一般的規(guī)律是,用參數(shù)表示的類型越多,代碼的靈活性和復(fù)用性也就越大。過多的泛化會導致代碼難以被其它的開發(fā)人員理解。
如果有約束,那么類型參數(shù)需要什么樣約束。一個良好的習慣是,盡可能使用最大的約束,同時保證可以處理所有需要處理的類型。例如,如果你知道你的泛型類只打算使用引用類型,那么就應(yīng)用這個類的約束。這樣可以防止無意中使用值類型,同時可以對T使用as運算符,并且檢查空引用;
把泛型行為放在基類中還是子類中。泛型類可以做基類。同樣非泛型類的設(shè)計中也應(yīng)考慮這一點。泛型基類的繼承規(guī)則;
是否實現(xiàn)一個或多個泛型接口。例如,要設(shè)計一個在基于泛型的容器中創(chuàng)建元素的類,可能需要實現(xiàn)類似IComparable
對于一個泛型類Node
// concrete type |
非泛型的具體類可以繼承自封閉構(gòu)造基類,但不能繼承自開放構(gòu)造基類。這是因為客戶代碼無法提供基類所需的類型參數(shù):
//No error. |
泛型的具體類可以繼承自開放構(gòu)造類型。除了與子類共用的類型參數(shù)外,必須為所有的類型參數(shù)指定類型:
//Generates an error. |
繼承自開放結(jié)構(gòu)類型的泛型類,必須指定參數(shù)類型和約束:
class NodeItem |
泛型類型可以使用多種類型參數(shù)和約束:
class KeyType |
開放結(jié)構(gòu)和封閉構(gòu)造類型可以用作方法的參數(shù):
void Swap |
當一個接口被指定為類型參數(shù)的約束時,只有實現(xiàn)該接口的類型可被用作類型參數(shù)。
可以在一個類型指定多個接口作為約束,如下:
class Stack |
一個接口可以定義多個類型參數(shù),如下:
IDictionary |
接口和類的繼承規(guī)則相同:
//Okay. |
具體類可以實現(xiàn)封閉構(gòu)造接口,如下:
class MyClass : IBaseInterface |
泛型類可以實現(xiàn)泛型接口或封閉構(gòu)造接口,只要類的參數(shù)列表提供了接口需要的所有參數(shù),如下:
//Okay. |
泛型類、泛型結(jié)構(gòu),泛型接口都具有同樣方法重載的規(guī)則。
泛型方法是聲名了類型參數(shù)的方法,如下:
void Swap |
下面的示例代碼顯示了一個以int作為類型參數(shù),來調(diào)用方法的例子:
int a = 1; |
也可以忽略類型參數(shù),編譯器會去推斷它。下面調(diào)用Swap的代碼與上面的例子等價:
Swap(a, b); |
靜態(tài)方法和實例方法有著同樣的類型推斷規(guī)則。編譯器能夠根據(jù)傳入的方法參數(shù)來推斷類型參數(shù);而無法單獨根據(jù)約束或返回值來判斷。因此類型推斷對沒有參數(shù)的方法是無效的。類型推斷發(fā)生在編譯的時候,且在編譯器解析重載方法標志之前。編譯器對所有同名的泛型方法應(yīng)用類型推斷邏輯。在決定(resolution)重載的階段,編譯器只包含那些類型推斷成功的泛型類。
在泛型類中,非泛型方法能訪問所在類中的類型參數(shù):
class List |
在泛型類中,定義一個泛型方法,和其所在的類具有相同的類型參數(shù);試圖這樣做,編譯器會產(chǎn)生警告CS0693。
class List warning CS0693: 類型參數(shù)“T”與外部類型“List |
在泛型類中,定義一個泛型方法,可定義一個泛型類中未定義的類型參數(shù):(不常用,一般配合約束使用)
class List void Add(List items) where U : T{} //常用 |
泛型方法通過多個類型參數(shù)來重載。例如,下面的這些方法可以放在同一個類中:
void DoSomething() { } |
在泛型類和泛型方法中會出現(xiàn)的一個問題是,如何把缺省值賦給參數(shù)化類型,此時無法預(yù)先知道以下兩點:
T將是值類型還是引用類型
如果T是值類型,那么T將是數(shù)值還是結(jié)構(gòu)
對于一個參數(shù)化類型T的變量t,僅當T是引用類型時,t = null語句才是合法的; t = 0只對數(shù)值的有效,而對結(jié)構(gòu)則不行。這個問題的解決辦法是用default關(guān)鍵字,它對引用類型返回空,對值類型的數(shù)值型返回零。而對于結(jié)構(gòu),它將返回結(jié)構(gòu)每個成員,并根據(jù)成員是值類型還是引用類型,返回零或空。
class GenericClass { T GetElement() { return default(T); } } |
感謝你能夠認真閱讀完這篇文章,希望小編分享的“.net中泛型的概述與分析”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學習!