泛型是 C# 2.0 引入的關鍵特性,它將「型別參數化」,使開發人員能編寫型別安全、高效能且可重用的程式碼。本文從基本定義、類別繼承、介面、委派、方法到約束條件,系統性介紹泛型程式設計的核心概念與實作技巧。
泛型類別宣告時在類別名稱後以尖括號指定型別參數(如 Test<T, S>),這些參數可用於欄位、屬性、方法簽章等成員:
public class Test<T, S>
{
private T name;
private S age;
public Test(T Name, S Age) { this.name = Name; this.age = Age; }
public void SetValue()
{
Console.WriteLine(name.ToString());
Console.WriteLine(age.ToString());
}
}
// 實例化時指定具體型別
Test<string, int> t = new Test<string, int>("SHY520", 22);
t.SetValue();
子類別繼承泛型父類別時,需滿足以下任一條件:
TestChild : Test<string, int>),子類別可為非泛型。TestChild<T, S> : Test<T, S>),雙方皆為泛型且參數對應。// 錯誤:找不到型別 T, S
public class TestChild : Test<T, S> { }
// 正確寫法
public class TestChild : Test<string, int> { }
public class TestChild<T, S> : Test<T, S> { }
public class TestChild<T, S> : Test<string, int> { }
泛型介面定義與繼承規則同類別。泛型委派允許在回傳值與參數套用型別參數:
public interface IList<T> { T[] GetElements(); }
public interface IDictionary<K, V> { void Add(K key, V value); }
delegate string GenericDelegate<T>(T value); // 泛型委派
// 使用範例
GenericDelegate<string> d1 = G; // G 為 static string G(string s)
GenericDelegate<int> d2 = new GenericDelegate<int>(F); // F 為 static string F(int i)
泛型方法僅在方法宣告處包含型別參數,可存在於泛型或非泛型類別中。支援多載與覆寫,覆寫時約束條件自動繼承:
public class GenericClass
{
// 泛型方法宣告
public T GetValue<T>(T t) { return t; }
// 呼叫時指定型別引數
public int UseMethod() { return this.GetValue<int>(10); }
// 多載非泛型版本
public int GetValue(int i) { return i; }
}
// 覆寫範例
abstract class Parent
{
public abstract K TEST<K, V>(K k, V v) where K : V;
}
class Child : Parent
{
public override T TEST<T, S>(T t, S s) { return t; } // 約束自動繼承
}
C# 僅支援顯式約束(where 子句),若無約束則型別參數僅能存取 System.Object 成員。四種主要約束:
class A { public void F1() {} }
class B { public void F2() {} }
class C<S, T>
where S : A // S 必須繼承自 A
where T : B // T 必須繼承自 B
{
// 可呼叫 s.F1()、t.F2()
}
interface IPrintable { void Print(); }
interface IComparable<T> { int CompareTo(T v); }
interface IKeyProvider<T> { T GetKey(); }
class Dictionary<K, V>
where K : IComparable<K>
where V : IPrintable, IKeyProvider<K>
{
// 可呼叫 k.CompareTo()、v.Print()、v.GetKey()
}
class A { public A() {} }
class B { public B(int i) {} }
class C<T> where T : new()
{
// 可執行 T t = new T();
}
C<A> c1 = new C<A>(); // 合法:A 有無參數建構函式
C<B> c2 = new C<B>(); // 錯誤:B 缺少無參數建構函式
public struct A { }
public class B { }
class C<T> where T : struct { } // T 必須為實值型別
class D<T> where T : class { } // T 必須為參考型別
C<A> c = new C<A>(); // 合法
C<B> c = new C<B>(); // 錯誤
善用泛型約束能在保持彈性的同時,確保型別安全並啟用特定功能,是掌握 C# 2.0 泛型程式設計的關鍵。