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>對象,而且不用再轉換來轉換去了。

似乎除了上述的情況需要泛型外,似乎我們實際中已經不需要泛型了,答案當然是否定的、

 

 

假設,我們需要編寫一個公共的方法。是對數組操作的,比如我們會寫一個方法,將數組擴充到指定長度

        /// <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>> 這樣也是可以的。

 

未完待與

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM