泛型方法將參數化能力下放至方法層級,配合類型推斷實現極致的調用便利性。本文系統梳理聲明語法、簽名規則、虛擬/重寫機制、調用與推斷算法、語法歧義消解、委托綁定、以及非泛型成員的限制。
generic_method_declaration:
attributes_opt method_modifiers_opt return_type member_name
type_parameter_list ( formal_parameter_list_opt )
type_parameter_constraints_clauses_opt method_body
Find<T>(T[] items, Test<T> test))。extern,其他修飾符皆可用。public delegate bool Test<T>(T item);
public class Finder {
public static T Find<T>(T[] items, Test<T> test) {
foreach (T item in items) if (test(item)) return item;
throw new InvalidOperationException("Item not found");
}
}
interface IX {
T F1<T>(T[] a, int i); // 錯誤:返回類型與參數名無關,兩者簽名相同
void F1<U>(U[] a, int i);
void F2<T>(int x); void F2(int x); // OK:類型參數數量不同
void F3<T>(T t) where T:A; void F3<T>(T t) where T:B; // 錯誤:約束不計入簽名
}
規則:兩個同名、同類型參數數量的泛型方法,其參數類型在所有可能封閉構造類型下不得產生相同簽名(約束忽略)。
class X<T> {
void F<U>(T t, U u) { } // 錯誤:X<int>.F<int> 產生兩個 F(int, int)
void F<U>(U u, T t) { }
}
abstract/virtual/override。abstract class Base {
public abstract T F<T,U>(T t, U u);
public abstract T G<T>(T t) where T: IComparable;
}
class Derived : Base {
public override X F<X,Y>(X x, Y y) { } // OK:參數名可不同
public override T G<T>(T t) { } // 錯誤:缺少 where T:IComparable
}
Find<int>(arr, test)。static void F<T>(int x, T y) { Console.WriteLine("One"); }
static void F<T>(T x, long y) { Console.WriteLine("Two"); }
F<int>(5, 324); // "One"
F<byte>(5, 324); // "Two"
F<double>(5, 324); // 錯誤:模糊
F(5, 324); // "One" (推斷 T=int)
F(5, 324L); // 錯誤:模糊
輸入:方法組、實參列表。輸出:每個類型參數的推斷類型實參。
A 對應參數 P 獨立推斷:P 與方法類型參數無關 / 實參為 null / 匿名方法 / 方法組 → 不推斷任何類型(但推斷成功)。P 為陣列類型,A 同秩陣列 → 遞歸用元素類型推斷;秩不同 → 失敗。P 為方法類型參數 MX → 推斷類型為 A。P 為構造類型 → 對 P 中每個類型參數 MX 求唯一 TX 使 A 隱式轉換至 P[MX:=TX]。多解/無解 → 失敗。(約束忽略)params 方法:先試普通形式,失敗再試擴展形式。
F(G<A,B>(7)):> 後緊跟 { } ] > : ; , . ? 之一 → 視為類型實參列表結束;否則視為大於運算子。
delegate int D(string s, int i);
delegate int E();
class X {
public static T F<T>(string s, T t) { ... }
public static T G<T>() { ... }
static void Main() {
D d1 = new D(F<int>); // 顯式
D d2 = new D(F); // 推斷 int
E e1 = new E(G<int>); // 顯式
E e2 = new E(G); // 錯誤:無法從返回類型推斷
}
}
它們自身不能有類型參數(雖可在泛型類中使用外部類型參數)。需泛型屬性語義時,請改用泛型方法。
A 到參數類型 P 的結構匹配,陣列遞歸、構造類型解方程、約束不參與。> 後跟特定符號才視為類型列表結束,保證向後兼容。泛型方法是 C# 類型系統表達力的關鍵延伸。精通其推斷與重載規則,能設計出如 LINQ 擴展方法般既強類型又極致簡潔的 API。下一篇將進入約束系統深度解析(20.7 章)。