共用方式為


泛型類型概觀

開發人員一直使用 .NET 中的泛型,無論是隱含還是明確。 當您在 .NET 中使用 LINQ 時,您是否注意到您正在使用 IEnumerable<T>? 或者,如果您曾經看到使用 Entity Framework 和資料庫互動的「通用儲存庫」線上範例,您有沒有注意到大部分的方法都會傳回 IQueryable<T>呢? 您可能想知道這些範例中的 T 是什麼,以及它在那裡的原因。

首先在 .NET Framework 2.0 中引進,泛型基本上是「程式代碼範本」,可讓開發人員定義 型別安全 的數據結構,而不需要認可實際數據類型。 例如,是一個List<T>可以宣告及與任何類型搭配使用,例如List<int>List<string>List<Person>

若要了解為什麼泛型很有用,讓我們來看看新增泛型之前和之後的特定類別: ArrayList。 在 .NET Framework 1.0 中,元素 ArrayList 的類型為 Object。 加入至集合的任何項目會以無訊息方式轉換成 Object。 從清單中讀取元素時,也會有相同的情況發生。 此過程稱為裝箱和拆箱,且會影響效能。 不過,除了效能之外,在編譯時期無法判斷清單中的數據類型,這會使程式碼變得很脆弱。 泛型可藉由定義每個清單實例將包含的數據類型來解決此問題。 例如,您只能將整數新增至 List<int> ,而且只能將 Person 新增至 List<Person>

泛型也可以在執行時使用。 運行時間知道您所使用的數據結構類型,而且可以更有效率地將它儲存在記憶體中。

下列範例是一個小程式,說明在運行時間了解數據結構類型的效率:

  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Diagnostics;

  namespace GenericsExample {
    class Program {
      static void Main(string[] args) {
        //generic list
        List<int> ListGeneric = new List<int> { 5, 9, 1, 4 };
        //non-generic list
        ArrayList ListNonGeneric = new ArrayList { 5, 9, 1, 4 };
        // timer for generic list sort
        Stopwatch s = Stopwatch.StartNew();
        ListGeneric.Sort();
        s.Stop();
        Console.WriteLine($"Generic Sort: {ListGeneric}  \n Time taken: {s.Elapsed.TotalMilliseconds}ms");

        //timer for non-generic list sort
        Stopwatch s2 = Stopwatch.StartNew();
        ListNonGeneric.Sort();
        s2.Stop();
        Console.WriteLine($"Non-Generic Sort: {ListNonGeneric}  \n Time taken: {s2.Elapsed.TotalMilliseconds}ms");
        Console.ReadLine();
      }
    }
  }

此程式會產生類似下列的輸出:

Generic Sort: System.Collections.Generic.List`1[System.Int32]
 Time taken: 0.0034ms
Non-Generic Sort: System.Collections.ArrayList
 Time taken: 0.2592ms

您可以在這裡注意到的第一件事是,排序泛型清單比排序非泛型清單要快得多。 您可能也會注意到泛型清單的類型是相異的 ([System.Int32]),而非泛型清單的類型則會一般化。 因為執行階段知道泛型 List<int> 的類型 Int32,所以它可以將清單項目儲存在記憶體中的基礎整數陣列中,而非泛型 ArrayList 則必須將每個清單項目轉換成物件。 如此範例所示,多餘的類型轉換會佔用時間並使清單排序速度變慢。

執行階段知道您的泛型類型的另一個優勢是更好的除錯效果。 當您在 C# 中偵錯泛型時,您知道每個元素在數據結構中的類型。 如果沒有泛型,您就不知道每個元素的類型為何。

另請參閱