C# 3.0 引入的擴展方法,允許以實例方法語法調用靜態方法。本質上是編譯器語法糖,將 obj.Method(args) 重寫為 StaticClass.Method(obj, args),極大提升 API 發現性與代碼流暢度。
this 修飾,指明擴展的目標類型public static class StringExtensions
{
// 擴展方法:this string s 表示擴展 string 類型
public static int ToInt32Ext(this string s)
{
return Int32.Parse(s);
}
// 普通靜態方法對比
public static int ToInt32Static(string s)
{
return Int32.Parse(s);
}
}
class Program
{
static void Main()
{
string s = "9";
int i = s.ToInt32Ext(); // 實例語法調用,無需傳遞 s
int j = StringExtensions.ToInt32Static(s); // 靜態語法調用
Console.WriteLine($"{i}, {j}"); // 輸出 9, 9
}
}
編譯器為擴展方法標註 ExtensionAttribute:
.method public hidebysig static int32 ToInt32Ext(string s) cil managed
{
.custom instance void [System.Core]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = (01 00 00 00)
// ... 方法體與普通靜態方法完全一致
}
Main 中調用被重寫為靜態調用:
IL_0008: call int32 ExtensionMethods.StringExtensions::ToInt32Ext(string)
| 源代碼形式 | 編譯為 |
|---|---|
expr.Identifier() | Identifier(expr) |
expr.Identifier(args) | Identifier(expr, args) |
expr.Identifier<T>() | Identifier<T>(expr) |
expr.Identifier<T>(args) | Identifier<T>(expr, args) |
using)中的擴展方法(按引用順序)// 必須知道類名
var result = MyLibraryClass.DesiredFunction(strName);
// IntelliSense 直接在實例上提示
var result = strName.DesiredFunction();
System.Linq.Enumerable 為 IEnumerable<T> 提供 Where、Select、OrderBy 等擴展方法,構建出優雅的查詢語法:
var adults = people.Where(p => p.Age >= 18)
.OrderBy(p => p.Name)
.Select(p => p.Name);
this T 為值傳遞,無法修改原結構體(需 ref this T,C# 7.2+ 支援)null 實例上調用,內部需自行判空擴展方法是 C# 3.0 為 LINQ 鋪路的關鍵特性,將「靜態工具方法」升級為「實例式體驗」,極大豐富了類型系統的表達能力。合理使用能讓 API 更易發現、代碼更流暢;濫用則會造成命名空間混亂。建議:優先考慮實例方法,實在無法修改源碼時再用擴展方法補足。