理解泛型類別內部運作機制,有助於掌握其型別安全與效能優勢的來源。本文詳細剖析 GenericClass<T> 的完整實作,重點說明其與非泛型 StandardClass 的關鍵差異:陣列宣告、方法簽章、以及型別參數如何流經整個類別設計。
public class GenericClass<T>
{
static int _count = 0;
int _maxItemCount;
T[] _items; // 關鍵差異 1:泛型陣列
int _currentItem = 0;
public GenericClass(int items)
{
_count++;
_maxItemCount = items;
_items = new T[_maxItemCount]; // 依型別參數建立陣列
}
public int AddItem(T item) // 關鍵差異 2:參數型別為 T
{
if (_currentItem < _maxItemCount)
{
_items[_currentItem] = item;
return _currentItem++;
}
throw new Exception("Item queue is full");
}
public T GetItem(int index) // 關鍵差異 3:回傳型別為 T
{
if (index >= _maxItemCount)
throw new ArgumentOutOfRangeException("index");
return _items[index];
}
public int ItemCount => _currentItem;
public override string ToString()
{
return $"There are {_count} instances of {this.GetType()} " +
$"which contains {_currentItem} items of type {_items.GetType()}";
}
}
// StandardClass
object[] _items; // 所有型別皆可存入,但失去型別資訊
// GenericClass<T>
T[] _items; // 編譯期即鎖定元素型別,執行期陣列為具體型別(如 string[]、int[])
影響:執行期 _items.GetType() 回傳實際陣列型別(如 System.String[]),而非 System.Object[]。這意味著 JIT 編譯器可為每個封閉建構型別生成最佳化機器碼。
// StandardClass
public int AddItem(object item) // 接受任何物件,值型別會被裝箱
// GenericClass<T>
public int AddItem(T item) // 僅接受 T 或其衍生型別,值型別直接存入陣列
效能差異:呼叫 AddItem(123) 時,非泛型版本產生 box IL 指令;泛型版本直接將整數寫入 int[] 陣列位址。
// StandardClass
public object GetItem(int index) // 回傳 object,呼叫端需轉型
// GenericClass<T>
public T GetItem(int index) // 直接回傳 T,型別安全
使用體驗:泛型版本消除 (string)list.GetItem(0) 等轉型語法,編譯器保證回傳值型別正確。
static int _count = 0; // 屬於開放型別 GenericClass<T>,所有封閉型別共享
注意:_count 計算的是 所有 GenericClass<T> 實例總數(包含 GenericClass<int>、GenericClass<string> 等)。若需分別計數,應改為實例欄位或使用 typeof(GenericClass<T>) 區分。
var gStr = new GenericClass<string>(3);
var gInt = new GenericClass<int>(3);
Console.WriteLine(gStr); // items of type System.String[]
Console.WriteLine(gInt); // items of type System.Int32[]
執行期陣列型別完整保留,這是泛型與 object 陣列的本質區別。
GenericClass<T> 透過三處關鍵替換(陣列元素型別、方法參數型別、方法回傳型別),將「型別參數化」貫徹至整個類別實作。這不僅提供編譯期型別檢查,更讓 JIT 編譯器為每個封閉建構型別生成專屬最佳化代碼,從根本上消除裝箱/拆箱與型別轉換開銷。