C#2.0新增功能02 泛型

  • 2019 年 10 月 4 日
  • 筆記

  C# 語言和公共語言運行時 (CLR) 的 2.0 版本中添加了泛型。 泛型將類型參數的概念引入 .NET Framework,這樣就可以設計具有以下特徵的類和方法:在客戶端代碼聲明並初始化這些類和方法之前,這些類和方法會延遲指定一個或多個類型。

泛型定義

 泛型是為所存儲或使用的一個或多個類型具有佔位符(類型形參)的類、結構、接口和方法。 泛型集合類可以將類型形參用作其存儲的對象類型的佔位符;類型形參呈現為其字段的類型和其方法的參數類型。 泛型方法可將其類型形參用作其返回值的類型或用作其形參之一的類型。

以下代碼舉例說明了一個簡單的泛型類定義。

public class Generic<T>  {      public T Field;  }

創建泛型類的實例時,指定用於替代類型形參的實際類型。 在類型形參出現的每一處位置用選定的類型進行替代,這會建立一個被稱為構造泛型類的新泛型類。 你將得到根據你選擇的類型而定製的類型安全類,如以下代碼所示。

public static void Main()  {      Generic<string> g = new Generic<string>();      g.Field = "A string";      //...      Console.WriteLine("Generic.Field           = "{0}"", g.Field);      Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName);  }

例如,通過使用泛型類型參數 T,可以編寫其他客戶端代碼能夠使用的單個類,而不會產生運行時轉換或裝箱操作的成本或風險,如下所示:

// 定義通用泛型類  public class GenericList<T>  {      public void Add(T input) { }  }    class TestGenericList  {      private class ExampleClass { }      static void Main()      {          // 定義 int 類型的集合          GenericList<int> list1 = new GenericList<int>();          list1.Add(1);            // 定義 string 類型的集合          GenericList<string> list2 = new GenericList<string>();          list2.Add("");            // 定義 ExampleClass 類類型的集合          GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();          list3.Add(new ExampleClass());      }  }

  泛型類和泛型方法兼具可重用性、類型安全性和效率,這是非泛型類和非泛型方法無法實現的。 泛型通常與集合以及作用於集合的方法一起使用。 .NET Framework 2.0 版類庫提供新的命名空間 System.Collections.Generic,其中包含幾個新的基於泛型的集合類。 建議所有定目標到 .NET Framework 2.0 及更高版本的應用程序都使用新增的泛型集合類,而不是舊的非泛型集合類(如 ArrayList)。 有關詳細信息,請參閱 .NET 中的泛型

當然,也可以創建自定義泛型類型和泛型方法,以提供自己的通用解決方案,設計類型安全的高效模式。 以下代碼示例演示了出於演示目的的簡單泛型鏈接列表類。 (大多數情況下,應使用 .NET Framework 類庫提供的 List<T> 類,而不是自行創建類。)在通常使用具體類型來指示列表中所存儲項的類型的情況下,可使用類型參數 T。 其使用方法如下:

  • AddHead 方法中作為方法參數的類型。
  • Node 嵌套類中作為 Data 屬性的返回類型。
  • 在嵌套類中作為私有成員 data 的類型。

請注意,T 可用於 Node 嵌套類。 如果使用具體類型實例化 GenericList<T>(例如,作為 GenericList<int>),則出現的所有 T 都將替換為 int

// 泛型 T 類型的類  public class GenericList<T>  {      // 嵌套類也定義成泛型T類型      private class Node      {          // 泛型類型 T 作為構造函數參數          public Node(T t)          {              next = null;              data = t;          }            private Node next;          public Node Next          {              get { return next; }              set { next = value; }          }            // 定義一個私有 T(類型) 數據類型的變量          private T data;            // T 類型作為屬性的返回類型          public T Data          {              get { return data; }              set { data = value; }          }      }        private Node head;        // 構造函數      public GenericList()      {          head = null;      }        // T 作為方法的參數類型      public void AddHead(T t)      {          Node n = new Node(t);          n.Next = head;          head = n;      }        public IEnumerator<T> GetEnumerator()      {          Node current = head;            while (current != null)          {              yield return current.Data;              current = current.Next;          }      }  }

以下代碼示例演示了客戶端代碼如何使用泛型 GenericList<T> 類來創建整數列表。 只需更改類型參數,即可輕鬆修改以下代碼,創建字符串或任何其他自定義類型的列表:

class TestGenericList  {      static void Main()      {          // 定義 int 類型的集合          GenericList<int> list = new GenericList<int>();            for (int x = 0; x < 10; x++)          {              list.AddHead(x);          }            foreach (int i in list)          {              System.Console.Write(i + " ");          }          System.Console.WriteLine("n 完成");      }  }

泛型主要有兩個優點:

  • 編譯時可以保證類型安全。
  • 不用做類型轉換,獲得一定的性能提升。

泛型概述

  • 使用泛型類型可以最大限度地重用代碼、保護類型安全性以及提高性能。
  • 泛型最常見的用途是創建集合類。
  • .NET Framework 類庫在 System.Collections.Generic 命名空間中包含幾個新的泛型集合類。 應儘可能使用這些類來代替某些類,如 System.Collections 命名空間中的 ArrayList
  • 可以創建自己的泛型接口、泛型類、泛型方法、泛型事件和泛型委託。
  • 可以對泛型類進行約束以訪問特定數據類型的方法。
  • 在泛型數據類型中所用類型的信息可在運行時通過使用反射來獲取。