今天咱們來學習在C#的泛型技巧,傳統的課本都在講解什麼是泛型,而後列舉一大堆代碼示例告訴你什麼是泛型,今天咱們就來聊聊更加本質的東西,我爲何要用泛型?它是來解決什麼問題的?底層原理是什麼?c++
簡單來講,泛型解決的是什麼問題呢?算法重用和提高性能的。程序員
最最經典的例子是什麼?就是微軟支持的List<T>類型,想必絕大多的程序員都是使用過這個類的。若是沒有這個類,咱們能夠想象下,若是要你開發一個算法類,支持對數組的長度動態擴展的,還支持一些廣泛的數組操做的話。你會怎麼寫?算法
好比我要寫 int 數據類型的數組操做功能,寫了一遍的 ListInt 類,若是這時候咱們須要寫一個 float 類型的數組操做對象,咱們又得寫一遍 ListFloat, 也就是說,每用到一個新的類型的時候,都須要寫一遍類,而這之間的代碼絕大部分都是類似的。數組
你可能會提出我搞一個 ListObject 類就能夠了,這樣就能夠知足全部的狀況了,恭喜你,這真的是個很不錯的想法,不管你的類型是什麼?都會轉換爲object進行數組的操做,這樣只要寫一套代碼就能夠了。只是,當你用了一段時間以後,它會碰到2個比較麻煩的問題性能
1. 我實例化了 ListObject 類,Add了不少了int類型的數據,我如今要獲取全部的int類型的數組,好比int[],這個比較麻煩,須要對全部object數據進行強制轉換。數組的長度比較大的時候,這時候性能就不好,爲何說c和c++性能高,都是地址基於地址的操做,沒有類型轉換一說。學習
2. 我實例化了 ListObject 類,Add了不少了int類型的數據,可是我在用的時候,很容易就誤覺得是float類型的,從而轉換失敗,下降了開發的效率。對象
這時候咱們就要讓泛型出場了,List<T>類型,將數組通常的操做邏輯都進行了封裝,add,remove,insert,clear,等等操做。當你須要使用int類型的時候,就能夠定義List<int>的對象,當你須要short類型的時候,就能夠定義List<short>對象,並且不用再轉換來轉換去了。blog
彷佛除了上述的狀況須要泛型外,彷佛咱們實際中已經不須要泛型了,答案固然是否認的、ci
假設,咱們須要編寫一個公共的方法。是對數組操做的,好比咱們會寫一個方法,將數組擴充到指定長度開發
/// <summary> /// 將一個數組進行擴充到指定長度,或是縮短到指定長度 -> /// Extend an array to a specified length, or shorten to a specified length or fill /// </summary> /// <typeparam name="T">數組的類型</typeparam> /// <param name="data">原先數據的數據</param> /// <param name="length">新數組的長度</param> /// <returns>新數組長度信息</returns> public static T[] ArrayExpandToLength<T>( T[] data, int length ) { if (data == null) return new T[length]; if (data.Length == length) return data; T[] buffer = new T[length]; Array.Copy( data, buffer, Math.Min( data.Length, buffer.Length ) ); return buffer; }
這麼來看,這個就特別是否寫成泛型,和類型無關的狀況。
以前是數組的例子,咱們再來看看另外一個實際的例子。咱們先看看代碼:
/// <summary> /// 操做結果的泛型類,容許帶一個用戶自定義的泛型對象,推薦使用這個類 /// </summary> /// <typeparam name="T">泛型類</typeparam> public class OperateResult<T> : OperateResult { #region Constructor /// <summary> /// 實例化一個默認的結果對象 /// </summary> public OperateResult( ) : base( ) { } /// <summary> /// 使用指定的消息實例化一個默認的結果對象 /// </summary> /// <param name="msg">錯誤消息</param> public OperateResult( string msg ) : base( msg ) { } /// <summary> /// 使用錯誤代碼,消息文原本實例化對象 /// </summary> /// <param name="err">錯誤代碼</param> /// <param name="msg">錯誤消息</param> public OperateResult( int err, string msg ) : base( err, msg ) { } #endregion /// <summary> /// 用戶自定義的泛型數據 /// </summary> public T Content { get; set; } }
當你的自定義類須要攜帶一個數據時,而這個數據多是任意類型的時候,這時候可使用泛型。好比這裏的 OperateResult<int> 就是很是好的例子。能夠用來攜帶任意的自定義的數據。甚至是數組
OperateResult<List<int>> 這樣也是能夠的。
未完待與