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

C# 2.0 泛型入門完全指南:型別參數、約束、靜態成員、方法重載與效能優勢

     編輯:關於C語言

為什麼需要泛型?

.NET 1.x 時代,集合類別 (如 Stack) 僅能用 object 儲存任意型別,導致兩大問題:

  1. 裝箱/拆箱:實值型別 (int, struct) 存入 object 需在堆積配置包裝物件,取出需拆箱,大量操作效能極差。
  2. 型別不安全:stack.Push(1); stack.Push("str"); 編譯通過,執行期 Pop() 轉型失敗拋出 InvalidCastException。

泛型解決方案


public class Stack
{
    private T[] _items;
    private int _top = -1;
    public Stack(int capacity) => _items = new T[capacity];
    public void Push(T item) => _items[++_top] = item;
    public T Pop() => _items[_top--];
    public T Peek() => _items[_top];
}
  • T 為型別參數 (佔位符),實例化時指定具體型別:var intStack = new Stack<int>(100);。
  • 型別安全:intStack.Push("str") 編譯錯誤。
  • 零裝箱:JIT 為每個封閉構造型別 (Stack<int>, Stack<string>) 產生專屬機器碼,實值型別直接內嵌儲存。

泛型型別參數約束 (where)

約束語法含義
基底類別where T : BaseClassT 必須繼承自 BaseClass (單一)
介面where T : IInterfaceT 必須實作介面 (可多個)
無參建構函式where T : new()T 必須有 public 無參建構函式
參考型別where T : classT 必須為 class/interface/delegate/array
實值型別where T : structT 必須為非 Nullable 實值型別
非受控型別where T : unmanagedC# 7.3+,T 為非受控型別 (可用於 stackalloc)
預設建構函式where T : notnullC# 8.0+,T 不可為 nullable

// 多重約束:T 繼承 Base 且實作 IComparable,且有無參建構函式
public class Node where T : BaseClass, IComparable, new() { ... }

// 多型別參數各自約束
public class Pair where T : class where U : struct { ... }

約束效益:在泛型類別內可呼叫約束保證的成員 (如 T.CompareTo、new T())。

泛型方法

方法層級引入型別參數,獨立於類別泛型參數。


public static void Swap(ref T a, ref T b) { T t=a; a=b; b=t; }
public void PushRange(Stack stack, params T[] items) { foreach(var i in items) stack.Push(i); }

// 呼叫:型別推論自動推導 T
Swap(ref x, ref y);
PushRange(intStack, 1,2,3,4,5);

泛型中的靜態成員

核心原則:每個封閉構造型別擁有獨立的靜態欄位/建構函式。


class Counter { public static int Count = 0; }

Counter.Count++;   // 1
Counter.Count++;   // 2
Counter.Count++; // 1 (獨立計數)
  • 靜態建構函式 (static Counter()) 在該封閉型別首次被存取 (建立實例或存取靜態成員) 時由 CLR 自動執行一次。
  • 泛型類別本身 (Counter<T>) 無靜態狀態,只有具體化後 (Counter<int>) 才有。

泛型類別中的方法多載與覆寫

多載解析規則

  • 編譯期針對開放型別 (Node<T,U>) 檢查簽名衝突,允許潛在衝突 (如 add(T,U)、add(U,T)、add(int,int) 共存)。
  • 實例化並呼叫時 (封閉型別) 才進行最終解枯:

class Node
{
    public T Add(T a, U b) => a;
    public T Add(U a, T b) => b;
    public int Add(int a, int b) => a + b; // 非泛型多載優先
}

var n1 = new Node(); n1.Add(2,3); // 呼叫 int Add(int,int) (非泛型優先)
var n2 = new Node(); n2.Add("s", 1); // 呼叫 Add(T,U)

若移除非泛型多載,Node.Add(2,3) 會因 Add(T,U) 與 Add(U,T) 簽名相同而編譯錯誤 (模糊)。

覆寫規則

同多載:衍生類別覆寫基底泛型虛擬方法時,簽名必須完全一致 (含型別參數)。

泛型應用範圍

  • 類別、結構、介面、委派、方法。
  • 委派泛型化:delegate TResult Func(T arg); (框架內建 Func/Action 族)。
  • 介面協變/逆變 (C# 4.0+ in/out):IEnumerable, IComparer。

總結

泛型是 C# 2.0 最具影響力的特性,實現 型別安全、高效能、程式碼重用 三贏。掌握 where 約束、靜態成員隔離、多載解析規則,能設計出優雅且高效的泛型庫。

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