擴充方法不僅能擴充具體類別,也能擴充介面。這為「介面演進」提供了新選擇:無需修改所有實作類別,即可為介面新增功能。本文深入探討介面擴充優勢、命名空間共存技巧、與實作類別同名方法的多型行為。
namespace Hongjun.Guo
{
// 原始介面
interface MyInterface
{
void Test01();
}
// 實作類別
public class MyClass : MyInterface
{
public void Test01() => Console.WriteLine("Test01");
}
// 擴充方法:為介面新增 MyTest002
static class MyExtensionMethods
{
public static void MyTest002(this MyInterface ii)
{
ii.Test01(); // 可呼叫介面既有方法
}
}
}
// 使用端
using Hongjun.Guo;
static void Main()
{
MyInterface mm = new MyClass();
mm.MyTest002(); // 輸出:Test01
}
傳統做法:介面新增方法 → 所有實作類別必須實作 → 若實作類別分散於多組件、甚至第三方封閉原始碼,修改成本極高。
擴充方法做法:僅在一處新增擴充方法,所有現有實作類別零修改即可獲得新功能。
將介面與其擴充方法放在同一命名空間:
using Hongjun.Guo; 引用介面using,擴充方法「自動可用」當介面擴充方法與實作類別擁有同名方法時:
interface MyInterface { void Test01(); }
static class MyExtensionMethods
{
public static void MyTest002(this MyInterface ii) => ii.Test01();
}
public class MyClass : MyInterface
{
public void Test01() => Console.WriteLine("Test01");
public void MyTest002() => Console.WriteLine("MyTest002"); // 實作類別同名方法
}
// 呼叫測試
MyInterface mm = new MyClass();
mm.MyTest002(); // 介面型別呼叫 → 輸出:Test01(擴充方法)
((MyClass)mm).MyTest002(); // 具體類別型別呼叫 → 輸出:MyTest002(實作方法)
| 呼叫者靜態型別 | 實際執行方法 | 原因 |
|---|---|---|
介面型別(MyInterface) | 擴充方法 | 介面無此實例方法,編譯器解析到擴充方法 |
具體類別型別(MyClass) | 實作類別方法 | 編譯器優先解析型別原生方法 |
這與「擴充方法 vs 原生方法」優先順序一致:靜態型別決定解析結果,體現編譯期多型。
private/protected 成員介面擴充方法是 C# 3.0 賦予開發者的強大工具,它:
善用此技術,能大幅降低系統耦合度,優雅解決介面演進難題。