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

.NET 類型系統深度解析(下):泛型原理、實作與約束完全指南

     編輯:關於.NET

一、泛型:解決類型轉換效能與安全的鑰匙

.NET 2.0 引入泛型前,開發者只能用 System.Object 或非泛型集合(如 ArrayList)處理多型資料,導致頻繁的裝箱/拆箱與型別轉換,不僅效能損耗大,且編譯期無法發現型別錯誤。泛型的出現,提供了「虛擬泛型」的完美解法:

  • 原理:原始碼中以型別參數(如 T)作為佔位符,首次編譯產生含佔位符的 IL;JIT 二次編譯時,依實際型別參數(如 string、int)替換佔位符,生成專屬原生代碼。
  • 優勢:避免裝箱/拆箱、編譯期強型別檢查、程式碼重用率高。

程式碼演示

// 定義泛型類別
class Human<T> {
    public void Say(T word) {
        Console.WriteLine(word.ToString());
    }
}
// 使用時指定型別
var h = new Human<string>();
h.Say("Hello"); // T 被替換為 string

IL 中可見 Human`1<T> 與 Say(!!0),JIT 時 !!0 替換為具體型別。

二、泛型集合實戰:List<T> vs ArrayList

ArrayList 允許任意型別混入,導致裝箱與執行期型別錯誤;List<T> 在定義時鎖定型別,編譯期即攔截錯誤:

var list = new List<int>();
list.Add("abc"); // 編譯錯誤:無法從 string 轉換為 int
list.Add(123);   // 正確

這體現了「錯誤越早發現越好」的工程原則。

三、泛型約束:精準限定型別能力

約束讓泛型類別能安全呼叫特定成員。語法:where T : 條件。

常見約束類型

  • class:參考型別(類別、介面、委派、陣列)。
  • struct:實值型別(排除 Nullable)。
  • new():需有公用無參建構函式(需置最後)。
  • 基底類別名:繼承自指定類別。
  • 介面名稱:實作指定介面(可多個)。
  • U:裸型別約束,T 必須為 U 或其衍生型別。

實戰範例:英雄裝備武器

interface IWeapon {
    string WeaponName { get; }
    int WeaponValue { get; }
}
class Sword : IWeapon { /* 實作 */ }

class Hero<T> where T : IWeapon, new() {
    int _attack = 100;
    public int AttackValue { get => _attack; set => _attack = value; }
    public void AddArm(T weapon) {
        _attack += ((IWeapon)weapon).WeaponValue;
    }
}
// 使用
var hero = new Hero<Sword>();
hero.AddArm(new Sword()); // 攻擊力增加 500

約束確保 T 具備 IWeapon 成員與無參建構函式,編譯期保證型別安全。

四、關於 var 的思考

C# 3.0 引入 var 隱含型別,編譯期由推斷決定實際型別,並非執行期動態,本質上仍屬靜態型別,與泛型的「編譯期具體化」不同,不宜視為「真泛型」。

總結

泛型以「佔位符 + JIT 具體化」機制,在不犧牲效能與型別安全前提下,實現了高度可重用的演算法與資料結構。善用泛型集合與約束,是寫出健壯、高效 .NET 程式碼的關鍵。

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