C 2 0之細說泛型

2022-02-21 07:07:51 字數 2450 閱讀 1539

在c#1中,arraylist總是會給人帶來困擾,因為它的引數型別是object,這就讓開發者無法把握集合中都有哪些型別的資料。如果對string型別的資料進行算術操作那自然會報錯,但是遺憾的是在編譯期不會給你任何的提示

c#2中引入的泛型極其耀眼,甚至有些人會因為泛型而忽略c#2中其它新加入的特性

回到上面的問題,arraylist帶來的不僅僅是上面那些困擾,object是所有型別的基類,但是我們在開發中它幾乎不會有它的身影,因為它包容一切,但是我們需要使用int做算術操作的時候就發生了問題,就是強制型別轉換。當我們需要使用string的substring方法ide也不會給你任何提示,因為它是object型別。

泛型帶來的就是這樣革命性的改變,允許你的引數型別為泛型型別。回到arraylist,泛型的典型就是list了,而t就是泛型型別,它是乙個未繫結型別(不明確的)。但是在我們使用的時候需要進行指定

liststrlist = new list();

這時我們去訪問它的元素時就會有string資料型別的智慧型提示,我們可以輕鬆的點出substring方法。這時 list就是已構造

的泛型型別。而且因為是顯示的,也不會有型別轉換的問題。效能上也是大大的提高,這時我們把執行時需要檢查的提前到了編譯時

這是乙個比較繞的概念,看名稱比較迷糊其實很容易理解。

泛型型別雖然也是型別,而t就是泛型型別,但它是開放的,可以是string,int,class等。開放型別無法建立例項,因為不知道建立什麼例項,而封閉型別可以建立例項,封裝型別就是指定了實際的資料型別,比如

泛型型別也不總是任意資料型別都可以的,在開發的時候我們常常需要對傳入的實際型別進行把握,如果外部使用時傳入了意外的型別,那麼就會引發bug。

引用型別約束

如果我們希望資料型別是引用型別,那麼我們可以 where t: class

值型別約束

如果我們希望資料型別是值 型別,那麼我們可以 where t: struct

建構函式約束

我們希望資料型別是擁有無參的建構函式,那麼我們可以 where t: new()

轉換型別約束

我們希望資料型別是可以轉換為我們想要指定的資料型別,比如某個基類的子類,某個介面的實現。我們可以 where t: person

我們還可以根據實際需要進行組合約束,但是需要注意的是不是所有的約束都可以組合在一起,比如 約束不可以既是引用型別約束又是值型別約束。

需要注意的是,這並不是我們常用的var型別推斷,而是泛型方法的型別推斷。

比如list.add("小明"); 這時小明很明顯是乙個字串,那麼這段**就可以簡化成 list.add("小明");

這部分主要討論的是泛型的效率問題與反射部分

都知道,相比較arraylist,泛型不會有拆箱裝箱的過程,除了這些他們在記憶體中儲存的方式也是不一樣的。比如arraylist的byte和list。arraylist會為每乙個位元組進行裝箱並儲存已裝箱值的引用。而list沒有額外的引用儲存。他們看起來如下圖

對於靜態型別與靜態字段還有靜態建構函式, 我們都知道他們只會初始化一次,並且之後不會發生改變。對於泛型來說同乙個泛型引數型別確實如此 ,每個封閉型別都有自己的靜態欄位集。它們是獨立的。

比如 lista;

listb;

listc;

listd;

我們可以看到a與d是乙個泛型引數型別,它們是靜態建構函式只會執行一次,但是b、c、a會走三次,因為型別不一樣。

jit編譯器處理泛型的時候,會把值型別翻譯成不同的本地碼,而引用型別翻譯成共享的本地碼。因為引用具有相同的大小。而值型別並不是。

我們在使用foreach的時候會感到很便利,有時候我們也會自己實現乙個迭代器,這很簡單,只要去實現ienumerable介面與ienumerator介面即可,但是如果我們發現泛型的介面又實現著非泛型的介面。如果沒有問題,泛型介面都應該繼承乙個對應的非泛型介面,這樣就可以實現協變性,在之前的c#版本中也會適用。

c#的泛型設計的非常的巧妙,但是也有一些存在的不足之處。

在物件導向開發中我們可以用子類去new基類,這是沒有問題的,但是對於泛型來說是不可以的,可以看到**第一行是報錯的。泛型不支援可變性,它們是不變體,這是為了型別安全著想

但是我們可以通過其它方法來實現可變性。最簡單的使用泛型介面,和編寫輔助類。在4.0中有了其它的解決方法

我們想要對泛型實參進行算術運算,但是並不是所有的型別都可以進行算術執行的。也沒有類似於 + - / *這種操作符的約束。我們可以使用表示式樹和動態特性解決此問題

這很直觀 ,上面所說的都無法使用泛型,我們不可以

public t property

當然這個是無解的。因為至少我們開發的時候不會有這樣的需求

C 2 0泛型介紹之簡單泛型類。

下面是乙個簡單的泛型類。public class genericclass f,t public genericclass f name,t age public f name set public t age set 這是乙個最簡單的泛型類了。f,t就是就是型別引數。可以是乙個物件,也可以是某種資...

c 2 0泛型學習 一

1using system 23public class stack 410 public stack int size 11 15 public void push object item 16 23 public object pop 24 30 else 31 35 36 37 2.使用泛型的...

C 2 0泛型程式設計基礎

最顯著的一點就是它引數化了型別,把型別作為引數抽象出來,從而使我們在實際的運用當中能夠更好的實現 的重複利用,同時它提供了更強的型別安全,更高的效率,不過在約束方面,它只支援顯示的約束,這樣在靈活性方面就顯得不是那麼好了。我覺得它之所以能夠提供更高的效率是因為泛型在例項化的時候採用了 on dema...