泛型程序設計詳解(一)

前言

  泛型是C#和.Net的一個重要概念,泛型不只是C#編程語言中的一部分,並且與程序集中的IL(Intermediate Language)代碼緊密的集成。html

  在平時編程過程當中,經常會出現編寫一些差很少的代碼塊,不一樣的僅是處理不一樣的數據類型。好比一個處理int數據的方法,如今新加了string類型的數據。是否是把以前的方法複製一遍,而後修改類型int爲string。固然這樣的方法是沒有錯的,那麼後面又新增了其餘的許多類型怎麼辦?仍是複製修改嗎?這樣代碼看上去很冗餘,很複雜。這時候泛型就出現了。下面咱們看下爲什麼使用泛型吧。編程

優勢

  下面介紹下泛型的優勢,尤爲是下面幾個:c#

    • 性能
    • 類型安全
    • 二進制代碼重用

 

  1、性能安全

    泛型的一個主要優勢就是性能,在泛型集合類和非泛型集合類中,對值類型使用非泛型集合類,在把值類型轉換爲引用類型和把引用類型轉換爲值類型的時候,須要進行裝箱和拆箱的操做(前面的文章中講到了拆箱和裝箱會形成必定的性能損失),當集合數據量大的時候形成的性能損失也就隨之的增大了。編程語言

    使用非泛型集合時:ide

            var list = new ArrayList(); list.Add(100);//裝箱 int-object
            int i = (int)list[0];//拆箱 object-int
            foreach (int item in list) { Console.WriteLine(item);//遍歷拆箱輸出
            }        

 

    使用泛型集合類時:函數

    

            var list = new List<int>(); list.Add(100);//無裝箱操做 
            int i =  list[0];//無拆箱拆箱 
            foreach (int item in list) { Console.WriteLine(item);//無拆箱操做
            }    

 

    減小裝箱拆箱操做,節省了性能消耗。這也就是泛型的主要優勢了。性能

  2、類型安全學習

    泛型另外一個優勢就是類型安全,這裏咱們仍是使用非泛型集合類ArrayList()和泛型集合類List<T>來作案例。spa

    非泛型集合類ArrayList():

    

            var list = new ArrayList(); list.Add(100);// 添加一個int類型
            list.Add("string");//添加一個string類型
            foreach (int item in list) { Console.WriteLine(item);//遍歷循環輸出
 } 這裏容許輸出和拋出異常: System.InvalidCastException:「Unable to cast object of type 'System.String' to type 'System.Int32'.」    

    沒法強制把」string」轉換成int類型。

    咱們再看泛型集合類:

        var list = new List<int>(); list.Add(100);// 添加一個int類型 list.Add("string");//添加一個string類型,編譯器報錯,沒法從string轉換到int
            foreach (int item in list) { Console.WriteLine(item);//遍歷循環輸出 }

    在添加」string」類型的時候編譯器報錯,沒法添加。這裏也就杜絕了後續的錯誤。這也就是保證了類型的安全。

 

  3、二進制代碼重用

    泛型容許更好的重用二進制代碼,泛型類型能夠定義一次,而且能夠再許多不一樣的類型實例化,相比C++來講,不用每次訪問源代碼。

    例如上面使用的泛型集合類,using System.Collections.Generic; 中的List<T>類,能夠用int,string,自定義類去實例化。

    泛型類型還能夠在一種語言定義,而後再其餘任何.Net語言中使用。

 

泛型類的功能

  這裏咱們能夠來了解下建立泛型類了以後,泛型類有哪些功能呢?

    • 默認值
    • 約束
    • 繼承
    • 靜態成員

  1、默認值

    在咱們定義了泛型類型以後如何賦值呢?

public class Tclass<T> { public static T Get() { T a = default; return a; } }

    由於在泛型中初始給值很差給,你說給null吧,null是給引用類型的,你是給0吧,這又是給值類型的,這時候出現了default,當時引用類型調用時就給null,當時值類型時就0。

 

  2、約束

    說到泛型類型的約束時,不得不提關鍵字where,where是用來限制參數的範圍的,若是不符合where條件指定的參數範圍,編譯是不容許經過的。

    這裏泛型類型的約束主要能夠分爲如下6中

    • Where T: class(類型參數必須是引用類型)
    • Where T:struct(類型參數必須是值類型)
         public class Tclass<T,U>
        where T:class //類型參數爲引用類型
        where U:struct  //類型參數爲值類型
             {}    

 

    • Where T:<接口名稱>(類型參數必須是指定的接口或者實現指定的接口)
     /// <summary>
    /// 接口 /// </summary>
    interface Itest { } /// <summary>
    /// 定義一個字典類型 /// </summary>
    /// <typeparam name="TK"></typeparam>
    /// <typeparam name="TV"></typeparam>
    class Dictionary<TK, TV>
      where TK : IComparable, IEnumerable where TV : Itest { public void Add(TK key, TV val) { } }

 

 

    • Where T:<基類名>(參數必須是指定的基類或者是派生自指定的基類)
    class Ttest { } class Tclass<T> where T:Ttest { }

 

    • Where T:new ()(這是一個構造函數的約束,指定參數類型必須有一個默認構造函數,當與其餘約束一塊兒使用時必須放在其最後)
  class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()   {   // ...   }

 

    • Where T1:T2(這個約束指定類型T1派生自泛型類型T2,也就是說T1的參數類型要和T2同樣)
  public class Tclass<T> where T:IComparable { }

 

 

  3、繼承

    泛型類型的繼承與普通類的繼承類似但不一樣。

    /// <summary>
    /// 抽象基類,泛型類型 /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class Ttest<T> { public abstract T Add(T x, T y); } /// <summary>
   /// 繼承抽象基類,實現int類型 /// </summary>
   /// <typeparam name="T"></typeparam>
    class Tclass<T> : Ttest<int> { public override int Add(int x, int y) => x + y; }

 

  4、靜態成員

    泛型類型的靜態成員須要特殊的關注,泛型類的靜態成員只能在類的一個實例中共享。

    /// <summary>
    /// 泛型類型,靜態字段x /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Ttest<T> { public static int x; } class Program { static void Main(string[] args) { Ttest<string>.x = 111; Ttest<int>.x = 222; Console.WriteLine(Ttest<string>.x); } }

    上面事例中最後輸出的爲111,

總結

  這裏咱們主要是介紹了泛型的優勢及泛型類型的功能。在咱們平常的編程中會發現不少地方可使用泛型。提升代碼的擴展性及重用性。同時也能夠減小對object類型的使用,採用泛型類型的使用來替代。較少對性能的消耗。咱們下一節主要是對泛型類型的協變及抗變進行必定的理解。

 

    只要認爲是對的就去作,堅持去作,不要在意別人的見解,哪怕是錯,至少你有去作過證實曾經你努力過。

 


 

 

                      c#基礎知識詳解系列

 

 

 

  歡迎你們掃描下方二維碼,和我一塊兒學習更多的C#知識

 

  

相關文章
相關標籤/搜索