寫在前面:此隨筆僅僅是做爲我的學習總結,有不對的地方,請各位前輩指正O(∩_∩)O........程序員
一: 什麼是泛型c#
泛型是c#2.0以後新特性,是一種語法糖.將大量的安全檢查從執行期轉移至了編譯期,使類型參數化.大至思想就是編譯時期肯定其類型,延遲思想.安全
二: 使用泛型架構
1: 泛型的出現,提升了性能,那麼沒有泛型以前是一個什麼樣子呢?函數
舉個例子:性能
好比,咱們要分別輸出一個數字和字符串,咱們須要像這樣寫:學習
/// <summary> /// 打印數字 /// </summary> /// <param name="i"></param> public void PrintInt(int i) { Console.WriteLine("this is a method print number: {0},this type is {1}", i, i.GetType()); } /// <summary> /// 打印字符串 /// </summary> /// <param name="s"></param> public void PrintString(string s) { Console.WriteLine("this is a method print string: {0},this type is {1}",s,s.GetType()); }
能夠看到上面兩個方法內部都是基本上相同的.那聰明的程序員們就思考怎麼能夠優化上面的代碼.咱們能夠知道object是全部的父類,那麼就有了下面這一個優化以後的代碼:優化
public void PrintObject(object o) { Console.WriteLine("this is a method print object: {0},this type is {1}", o,o.GetType()); }
這樣咱們就把兩個方法優化成了一個方法,達到了同樣的目的.接下來問題又來了,如今這樣的寫法,就又存在了一個問題,就是裝箱和拆箱的問題,一次兩個裝箱拆箱咱們彷佛能夠忽略,可是大量的進行裝箱和拆箱那就太損失性能啦.this
因爲這樣那樣的問題,聰明的程序員就思考,怎麼可以避免裝箱拆箱問題,又能將代碼變得簡單可讀的,就這樣泛型就隨之產生啦.來看看有了泛型以後上面的代碼又會變成什麼樣呢?spa
/// <summary> /// 泛型方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="param"></param> public void PrintGenerics<T>(T param) { Console.WriteLine("this is a generics method print param: {0},this type is {1}", param,param.GetType()); } //使用 common.PrintGenerics<int>(1);
common.PrintGenerics(1);
這樣就是一個泛型方法了.如今有幾個疑問就是:
a: T是一個什麼東西呢,之前都沒有見過?
答: 從文檔註釋,對T的解釋,T是一個類型參數,須要咱們傳入具體的類型實參,T其實是一個佔位符,在編譯以後就變成了 `1這樣一個佔位符.
b: 在調用的時候爲何能夠省略<int>呢?
答: 編譯器會根據傳入的參數,來推斷出具體的類型
c: 這種方式爲何就比經過object來輸出好呢?
答: 從上面的解釋能夠知道object是存在裝箱和拆箱問題的,會損耗性能.而泛型就不存在裝箱和拆箱的問題,由於從前面能夠知道泛型是在編譯的時候才知道類型,實際上編譯器在咱們不知道的時候根據他的類型建立了相應數據類型的副本方法,好比:
common.PrintGenerics<int>(1); //建立的副本方法相似於 public void PrintInt(int i) { Console.WriteLine("this is a method print number: {0},this type is {1}", i, i.GetType()); }
這樣就不存在值類型到引用類型的轉換.
2: 泛型還有哪些應用呢?
泛型類,泛型接口,泛型方法,泛型返回,泛型約束
2.1: 泛型約束:
泛型約束是個什麼東西呢?大概就是讓參數知足它的條件(2333,解釋不來 =_=||)
就好比:
common.PrintGenerics<Person>(new Person());
咱們此時的參數是一個person對象,那麼咱們想輸出person的名字,可是咱們發現這樣是沒有出現param.Name的.
這是爲何呢?
由於此時咱們的參數沒有添加約束,就至關因而一個object,那object裏面有name屬性嗎?很顯然是沒有的.舉個例子:就像咱們讓一個"str"字符串輸出它的name屬性,是不現實的,由於沒有.
這個時候咱們的約束就該上場啦
public void PrintGenericsPerson<T>(T p) where T: Person { Console.WriteLine("my name is :"+p.Name); }
泛型約束經過where來實現.
那麼疑問又來了:
a: 約束後的效果是什麼樣呢?
答: 如今咱們就只能person類型以及它的子類型來做爲參數啦.
b: 這樣寫和直接規定它的參數類型爲person有什麼區別嗎?
答: 我的認爲通常在肯定是person類型的時候,就不會在傳入其子類型做爲參數了,在作架構方面可能很是有用(我的理解不是很透徹)
c: 還有其餘的約束嗎?
答: class: 表示約束爲引用類型(此時傳一個數字就會出錯). struct: 表示約束爲值類型(DateTime爲值類型). new(): 表示約束參數要有無參數的構造函數.等等
2.2: 泛型的靜態成員變量
靜態成員在相同的封閉類間共享.不一樣的封閉類間不共享
開放類型:泛型類型沒有指定具體的數據類型.
封閉類型:泛型類型指定了具體的數據類型.
2.3: 泛型方法的重載
a: 是在實例方法被調用的時候檢查重載是否混淆,而不是在泛型類自己編譯時檢查
b: 當通常方法與泛型方法具備相同的簽名時,會覆蓋掉泛型方法,而使用通常的方法.