原則:
1、和C++的模板類似,C#的泛型本質就是類型的類型,
它定義了一種類型,它的每個實例化物件是一種具體的類型,所以稱之為類型的類型
2、它在實例化的時候分成兩種情況:
引用類型和值類型
因為引用型別本質是指針,是記憶體的位址,所以一定位長的機器上,指標變數所用的位元組數是一致的,如32位元機使用4位元組,
泛型本質作為一種定義類型的類型,編譯後會有一份二進位程式碼描述這個類型定義的特徵,存放在記憶體中。
這裡首先描述一下編譯原始碼之後,類型定義,實例化物件的記憶體分配情況,原始碼編譯之後肯定程式碼一個程式檔(如exe檔),在執行的時候載入到記憶體空間(現代os採用映射的方式,邏輯上佔用內存,物理上使用頁面調度的方式,用到那部分資料調那部分資料進物理內存);
定義一個類別的時候,編譯之後類別的描述(具有哪些資料成員,哪些成員函數,各自權限等等的資訊)形成exe檔案的一部分,運行後載入到內存,這部分二進位的資料設在記憶體的位址為0x0001;
實例一個類別物件的時候,視語言不同處理而定,在C++中,類別實例化物件分配記憶體於堆疊;在C#中,類別實例化物件分配記憶體於堆;這部分記憶體空間是在程式的記憶體空間(如windows32位元系統,程式記憶體空間為4G),區別於exe映射的那部分記憶體之外的剩餘記憶體中,實例化物件超出生存期或被從堆上釋放時,歸還記憶體空間給程式。
同樣的,泛型的編碼後的二進位資料包含在exe檔中,載入到記憶體中,
當實例化泛型的時候,也就是編譯出一個具體的類型的時候(注意,C#這個實例化泛型的過程是在編譯期間進行,也就是說程式碼中所用到的實例化的泛型,各個具體類型,編譯時產生二進位程式碼,並連同泛型本身的二進位程式碼都寫進exe檔),每個實例化的型別二進位程式碼需要在exe檔中佔多大的空間呢?
在C#中,要根據引用類型和值類型來區分,設一個泛型在程式的原始碼中實例化了兩個引用類型,兩個值類型,
則對於引用類型:
一個用4位元組的指針即可,兩個用了兩個指針,二進位資料都指向所用類型(如vector<myClass>中的myClass,myClass是一個定義好的類別類型,編譯之後有二進位資料存放在exe檔案中)的二進位資料的位址(載入到記憶體後相對位址轉換成記憶體位址),這是因為引用型別的實例化物件是分配在堆上,是在運行時候執行的,這時,從指標的位址取到myClass類型描述的二進位數據,算出一個實例化物件要佔用的記憶體空間,在堆上來分配。
對於值類型:
值類型,包括了結構體和預定義資料類型,以這樣的類型去實例化泛型的時候(如vector<int>,vector<double>),就會產生兩個類別的實際的二進位資料來表示類別描述,這樣在程式中當實例化它們的物件時,快捷(當然也可以採用類似引用那樣,在運行的時候去計算,去編碼,但是值類型分配在棧上,喪失靈活性為的就是取得效率,所以這樣執行)