1. 數組到泛型集合

  • 數組缺少初始化時大小的彈性
string[] names = new string[4];     // 需指定大小
  • 普通對象集合缺少類型安全
    ArrayList names = new ArrayList();
    names.AddRange(new object[]
    {
        "Rose",
        "Jack",
        new int?(5)     // 可合法進行編譯, 因為符合 object
    });
    foreach (string name in names) Console.WriteLine(name); 
    // 缺少型別檢查, 在執行隱性類型轉換(int? 轉 string)時會出錯
  • 專用對象集合缺少撰寫程式碼的靈活性(如無法以靜態方式寫通用方法)、且維護成本較高
    StringCollection names = new StringCollection();
    names.AddRange(new string[]
    {
        "Rose",
        "Jack",
        "Gozilla"
    });
    static void printNames(StringCollection names) 
    {
        foreach (string name in names) Console.WriteLine(name);
    }
  • 泛型可以解決以上問題
    1. 在初始化時不須先設定大小
    2. 在添加錯誤型別的元素,在編譯時期就會報錯
    3. 兼容各種類型,省去撰寫與維護的成本
List<string> names = new List<string>{
    "Rose",
    "Jack",
    "Gozilla"
};
static void printList(List<T> list) {
    foreach (T item in list) Console.WriteLine(item);
}

2. 靜態方法取代建構式

  • 由於在泛型函式調用時,會進行類型推斷,故可以透過靜態方法簡化建構式,可以省去指定泛型類型:
// 靜態泛型函式
public static Tuple<T1, T2> CreateTuple(T1 item1, T2 item2) 
{
    return new Tuple<T1, T2>(item1, item2);
}
// 泛型建構式   
var tuple1 = new Tuple<string, int>("Jack", 18);
var tuple2 = CreateTuple("Jack", 18);   // 由於類型推斷, 省去寫泛型型別

3. 類型約束

  • 類型約束可用來限制類型實參的類別:
public static void SortList<T>(List<T> items) where T : IComparable<T>
{
    // 因為限定 T 需要繼承 IComparable, 所以可以叫用其 CompareTo 方法
    items.Sort((x,y) => x.CompareTo(y));
}

4. 泛型類型的初始化與狀態

  • List<int>List<string> 雖油桐一個泛型類型 List<T> 限定,但在執行期會被當作兩個不同的類型
    • 範例1. 用 typeof 測試
      public static void PrintType<T>()
      {
          Console.WriteLine($"typeof(T) = {typeof(T)}");
          Console.WriteLine($"typeof(List<T>) = {typeof(List<T>)}");
      }
      public static void Main()
      {
          PrintType<string>();
          PrintType<int>();
      }  
      // typeof(T) = System.String
      // typeof(List<T>) = System.Collections.Generic.List`1[System.String]
      // typeof(T) = System.Int32
      // typeof(List<T>) = System.Collections.Generic.List`1[System.Int32]  
      
    • 範例2. 檢查靜態域
      class GenericCounter<T>
      {
          private static int value;
          static GenericCounter()
          {
              Console.WriteLine($"Initializing counter for {typeof(T)}");
          }
          public static void Increment()
          {
              value++;
          }
          public static void Display()
          {
              Console.WriteLine($"Counter for {typeof(T)}: {value}");
          }
      }
      public static void Main()
      {
          GenericCounter<string>.Increment();
          GenericCounter<string>.Increment();
          GenericCounter<string>.Display();
          GenericCounter<int>.Display();
          GenericCounter<int>.Increment();
          GenericCounter<int>.Display();
      }
      // Initializing counter for System.String
      // Counter for System.String: 2
      // Initializing counter for System.Int32
      // Counter for System.Int32: 0
      // Counter for System.Int32: 1