首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 泛型秘訣(1):何時使用泛型、泛型類型運作原理

     編輯:關於C#

泛型是 C# 2.0 引入的核心特性,提供型別安全、效能(避免 boxing)、程式碼重用。本文說明決策依據、並以 StandardClass(非泛型)與 GenericClass<T>(泛型)並列對比,展示 CLR 為每個封閉建構型別產生獨立型別的機制。

決策檢核表:何時使用泛型

  • 類別操作「未指定」的資料型別(集合、容器、工廠、比較器)。
  • 處理值型別時要避免 boxing/unboxing。
  • 需要編譯期強型別檢查,提早發現錯誤。
  • 面臨「程式碼膨脹」:為每種型別寫近似類別(StreamReaderList、StreamWriterList)。
  • 追求程式碼清晰、可讀、可維護。

並列對比:StandardClass vs GenericClass<T>


// 非泛型:使用 object 陣列
public class StandardClass {
    object[] _items;
    public int AddItem(object item) { /* ... */ }
    public object GetItem(int i) { /* ... */ }
}

// 泛型:型別參數 T
public class GenericClass {
    T[] _items;
    public int AddItem(T item) { /* ... */ }
    public T GetItem(int i) { /* ... */ }
}

關鍵差異表

CLR 型別生成機制


// 程式碼
var a = new StandardClass(); // 1
var b = new StandardClass(); // 2
var c = new StandardClass(); // 3

var g1 = new GenericClass();   // 型別 1
var g2 = new GenericClass();    // 型別 2
var g3 = new GenericClass(); // 型別 3
var g4 = new GenericClass(); // 型別 3 (共用)

// 輸出靜態計數器
// StandardClass: 3 instances of StandardClass, items: Object[]
// GenericClass: 1 instance of GenericClass`1[Boolean], items: Boolean[]
//               1 instance of GenericClass`1[Int32], items: Int32[]
//               2 instances of GenericClass`1[String], items: String[]

結論:非泛型類別在 CLR 中只有一個 MethodTable;泛型類別每個「封閉建構型別」(如 GenericClass)都有獨立的 MethodTable、靜態欄位、JIT 代碼。這是泛型能提供零 boxing、型別安全的根本原因。

進階觀察

  • 靜態欄位 _count 分屬各封閉型別,互不干擾。
  • typeof(GenericClass<>) 為開放型別(GenericClass`1),typeof(GenericClass) 為封閉型別。
  • 泛型方法(非泛型類別的方法有型別參數)同樣享有上述優勢。
  • 約束(where T: ...)進一步縮小型別參數範圍,啟用成員存取。

理解泛型在 CLR 層面的運作,能幫助你在架構設計時果斷選擇泛型、正確預期效能與行為。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
面向StandardClassGenericClass<T>
陣列型別object[]T[]
AddItem 參數objectT
GetItem 回傳objectT
型別安全運行期拋 InvalidCastException編譯期錯誤(GenericClass.AddItem(1))
值型別效能每次 Add/Get 發生 boxing/unboxing零 boxing,直接堆疊/內嵌儲存
取值轉型需 (string)obj.GetItem(0),可能失敗直接 string s = gen.GetItem(0),編譯保證