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

C# 泛型類別實作詳解:GenericClass<T> 核心架構分析

     編輯:關於C語言

前言

理解泛型類別內部運作機制,有助於掌握其型別安全與效能優勢的來源。本文詳細剖析 GenericClass<T> 的完整實作,重點說明其與非泛型 StandardClass 的關鍵差異:陣列宣告、方法簽章、以及型別參數如何流經整個類別設計。

GenericClass<T> 完整實作代碼

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()}";
    }
}

三大關鍵差異深度解析

1. 陣列宣告:T[] vs object[]

// StandardClass
object[] _items;  // 所有型別皆可存入,但失去型別資訊

// GenericClass<T>
T[] _items;  // 編譯期即鎖定元素型別,執行期陣列為具體型別(如 string[]、int[])

影響:執行期 _items.GetType() 回傳實際陣列型別(如 System.String[]),而非 System.Object[]。這意味著 JIT 編譯器可為每個封閉建構型別生成最佳化機器碼。

2. AddItem 方法簽章:T vs object

// StandardClass
public int AddItem(object item)  // 接受任何物件,值型別會被裝箱

// GenericClass<T>
public int AddItem(T item)  // 僅接受 T 或其衍生型別,值型別直接存入陣列

效能差異:呼叫 AddItem(123) 時,非泛型版本產生 box IL 指令;泛型版本直接將整數寫入 int[] 陣列位址。

3. GetItem 回傳型別:T vs object

// 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>) 區分。

ToString() 顯示的型別資訊

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 編譯器為每個封閉建構型別生成專屬最佳化代碼,從根本上消除裝箱/拆箱與型別轉換開銷。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved