C 泛型應用及原理

2021-09-25 16:02:52 字數 3781 閱讀 2584

泛型(generic)是c#語言2.0和通用語言執行時(clr)的乙個新特性。泛型為.net框架引入了型別引數(type parameters)的概念。

型別引數使得設計類和方法時,不必指定方法有乙個或多個具體引數,而是在呼叫方法的時候再去指定。

這意味著使用泛型的型別引數t,寫乙個方法mylist,客戶**可以這樣呼叫:mylist, mylist或 mylist,也就是說乙個方法就可以滿足不同場景的使用。

避免了執行時型別轉換或裝箱操作的代價和風險。

針對早期版本的通用語言執行時和c#語言的侷限,泛型提供了乙個解決方案。以前型別的泛化(generalization)是靠型別與全域性基類system.object的相互轉換來實現。比如.net框架基礎類庫的arraylist容器類,就是這種侷限的乙個例子。arraylist是乙個很方便的容器類,使用中無需更改就可以儲存任何引用型別或值型別。

相對於陣列來說,這種集合比陣列靈活(陣列長度固定,資料型別單一),但是這種便利是有代價的,這需要把任何乙個加入arraylist的引用型別或值型別都隱式地向上轉換成system.object(如上圖所示)。如果這些元素是值型別,那麼當加入到列表中時,它們必須被裝箱;當重新取回它們時,要拆箱。

型別轉換和裝箱、拆箱的操作都降低了效能;

在必須迭代(iterate)大容器的情況下,裝箱和拆箱的影響可能十分顯著。

另乙個侷限是

缺乏編譯時的型別檢查

,比如當使用者需要儲存使用者的年齡時,結果把使用者的姓名也存進去了,但是因為arraylist把任何型別都轉換為object,所以編譯的時候不會報錯,這個錯誤只有在程式執行過程中才會暴露出來。

arraylist和其他相似的類真正需要的是一種途徑,能讓客戶**在例項化之前指定所需的特定資料型別。這樣就不需要向上型別轉換為object,而且編譯器可以同時進行型別檢查。換句話說,arraylist需要乙個型別引數。這正是泛型所提供的。在system.collections.generic命名空間中的泛型list容器裡,同樣是把元素加入容器的操作,類似這樣:

如上圖所示,與arraylist相比,list建立的集合比arraylist更安全,比如定義的是int型別的約束,如果輸入「張珊」的字串就會直接報錯,而且不需要做裝箱的操作。並且list可以定義各種型別的集合,通俗的來說就是乙個方法可以完成多種功能。

總結下,當我們程式**有相同的邏輯,有可能是方法、介面、類或者委託,只是某些引數型別不同,我們希望**可以通用、復用,甚至是說為了偷懶,也可以說是在不確定型別的情況下,就應該考慮用泛型的思維去實現。

在泛型型別或泛型方法的定義中,型別引數是乙個佔位符(placeholder),通常為乙個大寫字母,如list中的t。在客戶**宣告、例項化該型別的變數時,把t替換為客戶**所指定的資料型別,當然這個t可以改為a、b、c等。c#中可以定義泛型方法、泛型介面、泛型類和泛型委託。

泛型類

public class basedal: sixcomhelper where t : class, new()

/// /// 查詢單個實體

///

/// 實體

/// sql

///

public t getonebysql(string sql)

return default(t);}}

泛型方法

//通過訂單表唯一標識值-修改訂單狀態

public tupleupdatepaystatus(t parameter)

;"; }

else if (typename == "string")

;";}

bool b = this.execute(sql_execute);

if (!b)

}catch (exception exmsg)

return new tuple(return_result, return_msg);

}

泛型介面

public inte***ce istore{}

//genericstore類宣告了2個型別引數t、w,泛型類可以直接實現泛型介面

public class genericstore: istore{}

泛型委託

//定義有乙個引數的泛型委託

public delegate void genericdelegate(t item);

//定義方法

public static void funcinfo(int i)

//例項化

genericdelegatem = new genericdelegate(funcinfo);

c#語言2.0版的.net框架類庫提供了乙個新的命名空間,system.collections.generic,其中包含了一些已經可以使用的泛型容器類和相關的介面。和早期版本的.net框架提供的非泛型容器類相比,這些類和介面更高效且是型別安全的。在設計、實現自定義的容器類之前,可以考慮使用或繼承下圖中的某乙個。

泛型類或介面

描述對應的非泛型型別

collection

icollection

為泛型容器提供基類

collectionbase

icollection

comparer

icomparer

icomparable

比較兩個相同泛型型別的物件是否相等、可排序。

comparer

icomparer

icomparable

dictionary

idictionary

表示用鍵組織的鍵/值對集合。

hashtable

idictionary

dictionary.keycollection

表示dictionary中鍵的集合。

none.

dictionary.valuecollection

表示dictionary中值的集合。

none.

ienumerable

ienumerator

表示可以使用foreach 迭代的集合。

ienumerable

ienumerator

keyedcollection

表示有鍵值的集合。

keyedcollection

linkedlist

表示雙向鍊錶。

none.

linkedlistnode

表示linkedlist中的節點。

none.

list

ilist

使用大小可按需動態增加的陣列實現 ilist 介面

arraylist

ilist

queue

表示物件的先進先出集合。

queue

readonlycollection

為泛型唯讀容器提供基類。

readonlycollectionbase

sorteddictionary

表示鍵/值對的集合,這些鍵和值按鍵排序並可按照鍵訪問,實現icomparer介面。

sortedlist

stack

表示物件的簡單的後進先出集合。

stack

C 泛型內部原理

泛型相當於c 的模板 泛型方法 static void fly t i,k t 泛型委託 delegate void mydelegate t1 t1,t2 t2 net中的func 泛型 eventhandler 委託事件 泛型約束 約束父類或者介面 aaawhere t idbconnectio...

c 泛型應用範例

queryable,擴充套件函式查詢 queryable,擴充套件函式查詢 針對單錶或者檢視查詢 查詢所有 var student db.queryable tolist var studentdynamic db.queryable todynamic var studentjson db.que...

C 泛型委託應用

泛型委託實現例如 list.find array.find 的功能,就是乙個工具 跨平台 通用 方便 using system.collections using system.collections.generic using unityengine using system 泛型和委託應用 pu...