C#2.0引入了泛型這個特性,由於泛型的引入,在一定程度上極大的增強了C#的生命力,可以完成C#1.0時需要編寫複雜代碼才可以完成的一些功能。但是作為開發人員,對於泛型可謂是又愛又恨,愛的是其強大的功能,以及該特性帶來的效率的提升,恨的是泛型在複雜的時候,會呈現相當複雜的文法結構。
這種複雜不僅是對於初學者,對於一些有開發經驗的.NET開發人員,也是一個不那麼容易掌握的特性。
接下來我們來瞭解一下C#2.0加入的特性:泛型。
一.泛型的基本特性概述
在實際項目開發中,任何API只要將object作為參數類型和傳回型別使用,就可能在某個時候涉及強型別轉換。提到強型別轉換,估計很多開發人員第一反應就是“效率”這個次,對於強型別的利弊主要看使用者使用的環境,天底下沒有絕對的壞事,也沒有絕對的好事,有關強型別的問題不是本次的重點,不做重點介紹。
泛型是CLR和C#提供的一種特殊機制,支援另一種形式的代碼重用,即“演算法重用”。泛型實現了類型和方法的參數化,泛型型別和方法也可以讓參數告訴使用者使用什麼類型。
泛型所帶來的好處:更好的編譯時間檢查,更多在代碼中能直接表現的資訊,更多的IDE支援,更好的效能。可能有人會疑問,為什麼泛型會帶來這麼多好處,使用一個不能區分不同類型的常規API,相當於在一個動態環境中訪問那個API。
CLR允許建立泛型引用和泛型實值型別,但是不允許建立泛型枚舉,並且CLR允許建立泛型介面和泛型委派,CLR允許在參考型別、實值型別或介面中定義泛型方法。定義泛型型別或方法時,為類型指定了任何變數(如:T)都稱為型別參數。(T是一個變數名,在原始碼中能夠使用一個資料類型的任何位置,都可以使用T)在C#中泛型參數變數要麼成為T,要麼至少一大寫T開頭。
二.泛型類、泛型介面和泛型委派概述
1.泛型類
泛型型別仍然是類型,所以可以從任何類型派生。使用一個泛型型別並指定類型實參時,實際是在CLR中定義一個新類型對象,新類型對象是從泛型派生自的那個類型派生的。
使用泛型型別參數的一個方法在基尼險那個JIT編譯時間,CLR擷取IL,用指定的類型實參進行替換,然後建立恰當的本地代碼。
如果沒有為泛型型別參數提供類型實參,那就麼就是未綁定泛型型別。如果指定了類型實參,該類型就是已構造類型。
已構造類型可以是開發或封閉的,開發類型還包含一個類ixngcanshu,而封閉類型則不是開發的,類型的每個部分都是明確的。所有代碼實際都是在一個封閉的已構造類型的上下文中執行。
泛型類在.NET的應用主要在集合類中,大多數集合類在System.Collections.Generic和System.Collections.ObjectModel類中。下面簡單的介紹一種泛型集合類:
(1).SynchronizedCollection:提供一個安全執行緒集合,其中包含泛型參數所指定類型的對象作為元素.
[ComVisible(false)]public class SynchronizedCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable { /// <summary> /// 初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 類的新執行個體。 /// </summary> public SynchronizedCollection(); /// <summary> /// 通過用於對安全執行緒集合的訪問進行同步的對象來初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 類的新執行個體。 /// </summary> /// <param name="syncRoot">用於對安全執行緒集合的訪問進行同步的對象。</param><exception cref="T:System.ArgumentNullException"> <paramref name="syncRoot"/> 為 null。</exception> public SynchronizedCollection(object syncRoot); /// <summary> /// 使用指定的可枚舉元素列表和用於對安全執行緒集合的訪問進行同步的對象來初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 類的新執行個體。 /// </summary> /// <param name="syncRoot">用於對安全執行緒集合的訪問進行同步的對象。</param> <param name="list">用於初始化安全執行緒集合的元素的 <see cref="T:System.Collections.Generic.IEnumerable`1"/> 集合。</param> <exception cref="T:System.ArgumentNullException"><paramref name="syncRoot"/> 或 <paramref name="list"/> 為 null。</exception> public SynchronizedCollection(object syncRoot, IEnumerable<T> list); /// <summary> /// 使用指定的元素數組和用於對安全執行緒集合的訪問進行同步的對象來初始化 <see cref="T:System.Collections.Generic.SynchronizedCollection`1"/> 類的新執行個體。 /// </summary> /// <param name="syncRoot">用於對安全執行緒集合的訪問進行同步的對象。</param> <param name="list">用於初始化安全執行緒集合的 <paramref name="T"/> 類型元素的 <see cref="T:System.Array"/>。</param> <exception cref="T:System.ArgumentNullException"><paramref name="syncRoot"/> 或 <paramref name="list"/> 為 null。</exception> public SynchronizedCollection(object syncRoot, params T[] list); /// <summary> /// 將項添加到安全執行緒唯讀集合中。 /// </summary> /// <param name="item">要添加到集合的元素。</param> <exception cref="T:System.ArgumentException">設定的值為 null,或者不是集合的正確泛型型別 <paramref name="T"/>。</exception> public void Add(T item); /// <summary> /// 從集合中移除所有項。 /// </summary> public void Clear(); /// <summary> /// 從特定索引處開始,將集合中的元素複製到指定的數組。 /// </summary> /// <param name="array">從集合中複製的 <paramref name="T "/>類型元素的目標 <see cref="T:System.Array"/>。</param> <param name="index">複製開始時所在的數組中的從零開始的索引。</param> public void CopyTo(T[] array, int index); /// <summary> /// 確定集合是否包含具有特定值的元素。 /// </summary> /// /// <returns> /// 如果在集合中找到元素值,則為 true;否則為 false。 /// </returns> /// <param name="item">要在集合中定位的對象。</param> <exception cref="T:System.ArgumentException">設定的值為 null,或者不是集合的正確泛型型別 <paramref name="T"/>。</exception> public bool Contains(T item); /// <summary> /// 返回一個逐一查看同步集合的枚舉數。 /// </summary> /// /// <returns> /// 一個 <see cref="T:System.Collections.Generic.IEnumerator`1"/>,用於訪問集合中儲存的類型的對象。 /// </returns> public IEnumerator<T> GetEnumerator(); /// <summary> /// 返回某個值在集合中的第一個匹配項的索引。 /// </summary> /// /// <returns> /// 該值在集合中的第一個匹配項的從零開始的索引。 /// </returns> /// <param name="item">從集合中移除所有項。</param><exception cref="T:System.ArgumentException">設定的值為 null,或者不是集合的正確泛型型別 <paramref name="T"/>。</exception> public int IndexOf(T item); /// <summary> /// 將一項插入集合中的指定索引處。 /// </summary> /// <param name="index">要從集合中檢索的元素的從零開始的索引。</param><param name="item">要作為元素插入到集合中的對象。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小於零或大於集合中的項數。</exception> <exception cref="T:System.ArgumentException">設定的值為 null,或者不是集合的正確泛型型別 <paramref name="T"/>。</exception> public void Insert(int index, T item); /// <summary> /// 從集合中移除指定項的第一個匹配項。 /// </summary> /// /// <returns> /// 如果從集合中成功移除了項,則為 true;否則為 false。 /// </returns> /// <param name="item">要從集合中移除的對象。</param> public bool Remove(T item); /// <summary> /// 從集合中移除指定索引處的項。 /// </summary> /// <param name="index">要從集合中檢索的元素的從零開始的索引。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小於零或大於集合中的項數。</exception> public void RemoveAt(int index); /// <summary> /// 從集合中移除所有項。 /// </summary> protected virtual void ClearItems(); /// <summary> /// 將一項插入集合中的指定索引處。 /// </summary> /// <param name="index">集合中從零開始的索引,在此處插入對象。</param><param name="item">要插入到集合中的對象。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小於零或大於集合中的項數。</exception> <exception cref="T:System.ArgumentException">設定的值為 null,或者不是集合的正確泛型型別 <paramref name="T"/>。</exception> protected virtual void InsertItem(int index, T item); /// <summary> /// 從集合中移除指定 <paramref name="index"/> 處的項。 /// </summary> /// <param name="index">要從集合中檢索的元素的從零開始的索引。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小於零或大於集合中的項數。</exception> protected virtual void RemoveItem(int index); /// <summary> /// 使用另一項替換指定索引處的項。 /// </summary> /// <param name="index">要替換的對象的從零開始的索引。</param><param name="item">要替換的對象。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小於零或大於集合中的項數。</exception> protected virtual void SetItem(int index, T item); /// <summary> /// 返回一個逐一查看同步集合的枚舉數。 /// </summary> /// /// <returns> /// 一個 <see cref="T:System.Collections.Generic.IEnumerator`1"/>,用於訪問集合中儲存的類型的對象。 /// </returns> IEnumerator IEnumerable.GetEnumerator(); /// <summary> /// 從特定索引處開始,將集合中的元素複製到指定的數組。 /// </summary> /// <param name="array">從集合中複製的 <paramref name="T"/> 類型元素的目標 <see cref="T:System.Array"/>。</param> <param name="index">複製開始時所在的數組中的從零開始的索引。</param> void ICollection.CopyTo(Array array, int index); /// <summary> /// 向集合中添加一個元素。 /// </summary> /// /// <returns> /// 新元素的插入位置。 /// </returns> /// <param name="value">要添加到集合中的對象。</param> int IList.Add(object value); /// <summary> /// 確定集合是否包含具有特定值的元素。 /// </summary> /// <returns> /// 如果在集合中找到元素 <paramref name="value"/>,則為 true;否則為 false。 /// </returns> /// <param name="value">要在集合中定位的對象。</param><exception cref="T:System.ArgumentException"><paramref name="value"/> 不是集合所含類型的對象。</exception> bool IList.Contains(object value); /// <summary> /// 確定集合中某個元素的從零開始的索引。 /// </summary> /// /// <returns> /// 如果在集合中找到,則為 <paramref name="value"/> 的索引;否則為 -1。 /// </returns> /// <param name="value">集合中要確定其索引的元素。</param> int IList.IndexOf(object value); /// <summary> /// 將某個對象插入到集合中的指定索引處。 /// </summary> /// <param name="index">從零開始的索引,將在該位置插入 <paramref name="value"/>。</param><param name="value">要在集合中插入的對象。</param> <exception cref="T:System.ArgumentOutOfRangeException">指定的 <paramref name="index"/> 小於零或大於集合中的項數。</exception> <exception cref="T:System.ArgumentException">設定的 <paramref name="value"/> 為 null,或者不是集合的正確泛型型別 <paramref name="T"/>。</exception> void IList.Insert(int index, object value); /// <summary> /// 從集合中移除作為元素的指定對象的第一個匹配項。 /// </summary> /// <param name="value">要從集合中移除的對象。</param> void IList.Remove(object value); }
(2).KeyedByTypeCollection:提供一個集合,該集合的項是用作鍵的類型。
[__DynamicallyInvokable] public class KeyedByTypeCollection<TItem> : KeyedCollection<Type, TItem> { /// <summary> /// 初始化 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 類的新執行個體。 /// </summary> public KeyedByTypeCollection(); /// <summary> /// 根據指定的對象枚舉初始化 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 類的新執行個體。 /// </summary> /// <param name="items">泛型型別 <see cref="T:System.Object"/> 的 <see cref="T:System.Collections.Generic.IEnumerable`1"/>,用於初始化集合。</param> <exception cref="T:System.ArgumentNullException"><paramref name="items"/> 為 null。</exception> public KeyedByTypeCollection(IEnumerable<TItem> items); /// <summary> /// 返回集合中第一個具有指定類型的項。 /// </summary> /// /// <returns> /// 如果為參考型別,則傳回型別 <paramref name="T"/> 的對象;如果為實值型別,則傳回型別 <paramref name="T"/> 的值。 如果集合中不包含類型 <paramref name="T"/> 的對象,則傳回型別的預設值:如果是參考型別,預設值為 null;如果是實值型別,預設值為 0。 /// </returns> /// <typeparam name="T">要在集合中尋找的項的類型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public T Find<T>(); /// <summary> /// 從集合中移除具有指定類型的對象。 /// </summary> /// /// <returns> /// 從集合中移除的對象。 /// </returns> /// <typeparam name="T">要從集合中移除的項的類型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public T Remove<T>(); /// <summary> /// 返回 <see cref="T:System.Collections.Generic.KeyedByTypeCollection`1"/> 中包含的類型 <paramref name="T"/> 的對象的集合。 /// </summary> /// /// <returns> /// 一個類型 <paramref name="T"/> 的 <see cref="T:System.Collections.ObjectModel.Collection`1"/>,包含來自原創組合的類型 <paramref name="T"/> 的對象。 /// </returns> /// <typeparam name="T">要在集合中尋找的項的類型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public Collection<T> FindAll<T>(); /// <summary> /// 從集合中移除所有具有指定類型的元素。 /// </summary> /// /// <returns> /// <see cref="T:System.Collections.ObjectModel.Collection`1"/>,包含來自原創組合的類型 <paramref name="T"/> 的對象。 /// </returns> /// <typeparam name="T">要從集合中移除的項的類型。</typeparam> [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public Collection<T> RemoveAll<T>(); /// <summary> /// 擷取集合中包含的某個項的類型。 /// </summary> /// /// <returns> /// 集合中指定的 <paramref name="item"/> 的類型。 /// </returns> /// <param name="item">集合中要檢索其類型的項。</param><exception cref="T:System.ArgumentNullException"><paramref name="item"/> 為 null。</exception> [__DynamicallyInvokable] protected override Type GetKeyForItem(TItem item); /// <summary> /// 在集合中的特定位置插入一個元素。 /// </summary> /// <param name="index">從零開始的索引,應在該位置插入 <paramref name="item"/>。</param><param name="item">要在集合中插入的對象。</param> <exception cref="T:System.ArgumentNullException"><paramref name="item"/> 為 null。</exception> [__DynamicallyInvokable] protected override void InsertItem(int index, TItem item); /// <summary> /// 使用一個新對象替換指定索引處的項。 /// </summary> /// <param name="index">要替換的 <paramref name="item"/> 的從零開始的索引。</param><param name="item">要添加到集合中的對象。</param> <exception cref="T:System.ArgumentNullException"><paramref name="item"/> 為 null。</exception> [__DynamicallyInvokable] protected override void SetItem(int index, TItem item); }
CLR支援泛型委派,目的是保證任何類型的對象都能以一種型別安全的方式傳給一個回調方法。泛型委派允許一個孩子類型執行個體在傳給一個回調方法時不執行任何裝箱處理。委託時機只提供了4個方法:一個構造器,一個Invlke方法,一個BeginInvoke方法和一個EndInvoke方法。如果定義的一個委託類型指定了型別參數,編譯器會定義委託類的方法,用指定的型別參數替換方法的參數類型和實值型別。
以上就是C#編程基礎之泛型方法解析(上)的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!