C#高級(jí)靜態(tài)語言效率利器之泛型詳解
引入
所謂泛型,就是創(chuàng)建一個(gè)函數(shù),對(duì)所有數(shù)據(jù)類型都生效。最常見的例子就是運(yùn)算符,畢竟1+1=2,1.0+1.0=2.0,足以看出+是對(duì)多種數(shù)據(jù)類型起作用的。
但是,如想創(chuàng)建一個(gè)函數(shù)add(int a, int b),那么輸入add(1.0, 1.0)是肯定要報(bào)錯(cuò)的,VS直接就給標(biāo)紅了。
泛型的出現(xiàn),就很好地解決了這個(gè)尷尬的問題
T add<T>(T a, T b) { dynamic d1 = a; dynamic d2 = b; return (T)(d1 + d2); } Console.WriteLine(add<int>(1, 1)); Console.WriteLine(add<double>(1.0, 1.0));
上面代碼中,T表示某種數(shù)據(jù)類型,在調(diào)用函數(shù)add時(shí),根據(jù)add后面的<>加以聲明。
但如果就此就寫return a+b顯然也是不行的,因?yàn)?這種運(yùn)算符并沒有對(duì)T進(jìn)行重載,編輯器并不會(huì)允許兩種未知的類型相加。
這個(gè)時(shí)候就需要用到dynamic,用來讓編輯器放棄類型檢查,將任何可能發(fā)生的錯(cuò)誤都留給運(yùn)行階段。
最后,運(yùn)行結(jié)果為
2
2
類型約束
dynamic用著確實(shí)爽,但后果就是責(zé)任自負(fù),這玩意要是用在團(tuán)隊(duì)協(xié)作的場合,簡直就是災(zāi)難,畢竟并非所有對(duì)象都可以駕馭加法。
所以,C#的泛型,是可以被約束的泛型,關(guān)鍵就是where,將上述代碼寫為
T add<T>(T a, T b) where T : struct{ dynamic d1 = a; dynamic d2 = b; return (T)(d1 + d2); }
where T : struct表示T必須是數(shù)值類型的一種,所以編譯器的類型檢查仍會(huì)發(fā)揮作用,在調(diào)用add時(shí),如果T不是數(shù)值類型,就會(huì)報(bào)錯(cuò)。
C#一共有5種約束方案,列表如下
類別 | 條件 |
---|---|
struct | T必須是值類型 |
class | T必須是引用類型 |
new() | T必須有無參數(shù)的構(gòu)造函數(shù) |
基類名 | T必須是基類或派生自基類 |
接口名 | T必須是指定接口 |
裸類型 |
不同類型的約束,或相同類型不同種類的約束,一般是可以混用的,如果不能混用,編譯器會(huì)提醒。比如struct幾乎不能和其他類型混用。如果new()參與了約束,則放在最后。
子類泛型
除了函數(shù)可以采用泛型,類當(dāng)然也可以,不僅可以,而且還能繼承。
class MyList<T> { public T[] a; public MyList(){} //無參數(shù)的構(gòu)造函數(shù),用于繼承 public MyList(int n){ a = new T[n]; } public T this[int index]{ get => a[index]; set => a[index] = value; } ???????}
MyList相當(dāng)于是給數(shù)組套了一層殼,其構(gòu)造函數(shù)并不存在什么難以理解的地方,唯一有些問題的可能是下面的索引器public T this[int index],這種寫法可以實(shí)現(xiàn)方括號(hào)形式的索引。
可以測(cè)試一下
var a = new MyList<int>(5); for (int i = 0; i < 5; i++) { a[i] = i; Console.WriteLine(a[i]); }
結(jié)果就不粘貼了,接下來新建一個(gè)子類
class MyStack<T> : MyList<T> { public MyStack(int n) { a = new T[n]; } public T Pop() { T p = a[a.Length- 1]; a = a[0..(a.Length-1)]; return p; } }
然后測(cè)試一下
var a = new MyStack<int>(3); for (int i = 0; i < 3; i++) { a[i] = i; } for (int i = 0; i < 3; i++) { Console.WriteLine(a.Pop()); }
結(jié)果為
2
1
0
常用的泛型數(shù)據(jù)結(jié)構(gòu)
C#通過泛型定義了很多數(shù)據(jù)結(jié)構(gòu),例如在講解switch...case時(shí)提到的字典
Dictionary<int, string> card = new Dictionary<int, string> { {1,"A" }, {11, "J" }, {12, "Q" }, {13, "K" } };
這種<U, V>的寫法,正是泛型的特點(diǎn),其中U, V就是可以隨意聲明的變量。如果查看字典的類型參數(shù),可以發(fā)現(xiàn)其定義方法是這樣的
public class Dictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, ... where TKey : notnull
考慮到本節(jié)并不是為了將面向?qū)ο?,所以字典繼承的那一大坨類就省略了,關(guān)鍵是where Tkey:notnull,也就是說,字典對(duì)鍵值對(duì)的要求只有一個(gè),就是鍵不得為null。
除了字典之外,還有一些常見的數(shù)據(jù)結(jié)構(gòu)采用了泛型,列表如下,沒事兒可以練習(xí)練習(xí)。
數(shù)據(jù)結(jié)構(gòu) | 說明 | 常用方法 |
---|---|---|
List<T> | 泛型列表 | Add, Remove, RemoveAt |
LinkedList<T> | 雙端鏈表 | AddFirst, AddLast, RemoveFirst, RemoveLast |
Queue<T> | 先進(jìn)先出列表 | Enqueue, Dequeue |
Stack<T> | 棧,先進(jìn)后出 | Push, Pop |
泛型委托
委托,是函數(shù)的函數(shù);泛型,可以讓函數(shù)的參數(shù)類型更加靈活,二者結(jié)合在一起,就是更加靈活的函數(shù)的函數(shù),即泛型委托。
只要學(xué)過了泛型和委托,那么對(duì)泛型委托將毫無理解上的難度,回想前面定義的運(yùn)算符委托
delegate int Op(int a, int b);
再回想定義泛型時(shí)的<T>,那么泛型委托可以非常簡單地定義出來
delegate T Op<T>(T a, T b);
然后就可以根據(jù)委托,建立一個(gè)泛型函數(shù)
T add<T>(T a, T b) { dynamic d1 = a; dynamic d2 = b; return (T)(d1 + d2); } var addTest = new Op<int>(add<int>); //也可以省略add后的<int>,寫成下面的形式 //var addTest = new Op<int>(add); Console.WriteLine(addTest(3, 5));
運(yùn)行之后控制臺(tái)出現(xiàn)了8,就是這么簡單。
到此這篇關(guān)于C#高級(jí)靜態(tài)語言效率利器之泛型詳解的文章就介紹到這了,更多相關(guān)C#泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# WinForm開發(fā)中使用XML配置文件實(shí)例
這篇文章主要介紹了C# WinForm開發(fā)中使用XML配置文件實(shí)例,本文詳細(xì)講解了如何使用一個(gè)XML文件作為WinForm的配置文件,需要的朋友可以參考下2014-08-08C#實(shí)現(xiàn)獲取計(jì)算機(jī)信息的示例代碼
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)獲取計(jì)算機(jī)軟硬件信息的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下2024-01-01C#實(shí)現(xiàn)在PDF文檔中應(yīng)用多種不同字體
在PDF文檔中,可繪制不同字體樣式、不同語言的文字,可通過使用Standard字體、TrueType字體、CJK字體或者自定義(私有)等字體類型。本文將具體介紹實(shí)現(xiàn)的方法,需要的可以參考一下2022-01-01C#中使用Cache框架快速實(shí)現(xiàn)Cache操作
這篇文章介紹了C#中使用Cache框架快速實(shí)現(xiàn)Cache操作的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06