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

C# 3.0 擴展方法進階:設計動機、優先級規則與實戰模式

     編輯:關於C語言

為什麼需要擴展方法?

傳統面向對象設計中,為現有類型添加功能只有兩條路:繼承(受限於密封類)或修改源碼(第三方庫不可改)。擴展方法提供第三條路:靜態語法糖實現的「開放封閉」增強,無需修改原類型、無需繼承、無運行期開銷。

核心價值

  • 發現性極強:IDE 智能提示自動顯示,如同原生實例方法
  • 零耦合擴展:第三方庫、BCL 類型、介面均可擴展
  • 鏈式流式 API 基石:LINQ、Fluent API 皆建於此

擴展方法完整語法規範

public static class Extensions
{
    // 基礎形式:擴展類型為第一參數,this 修飾
    public static void Foo(this string s, string param) { ... }
    
    // 泛型擴展
    public static TResult Map(this TSource source, Func selector) 
        => selector(source);
    
    // 擴展介面(極其強大)
    public static void ForEach(this IEnumerable source, Action action) { ... }
}

優先級解析:避免「方法劫持」陷阱

調用解析順序(高→低):

  1. 目標類型的實例方法(含繼承)
  2. 目標類型的擴展方法(當前命名空間)
  3. 外層 using 命名空間的擴展方法(越近優先級越高)

實戰驗證:同名方法衝突

namespace Demo
{
    public class MyClass 
    { 
        public void Print() => Console.WriteLine("實例方法"); 
    }
    
    public static class MyExtensions
    {
        public static void Print(this MyClass c) => Console.WriteLine("擴展方法");
    }
}

// 調用
var obj = new MyClass();
obj.Print(); // 輸出:實例方法
// 擴展方法被「隱藏」,除非顯式調用:MyExtensions.Print(obj);

結論:擴展方法永遠不會覆蓋實例方法,安全但需注意命名衝突導致的困惑。

三大經典實戰模式

1. 參數化擴展 —— 增強現有功能

public static class StringExtensions
{
    public static string Truncate(this string s, int maxLength, string suffix = "...")
        => s.Length <= maxLength ? s : s.Substring(0, maxLength) + suffix;
}

// 用法
var title = "這是一個很長的標題需要截斷處理";
var shortTitle = title.Truncate(10); // "這是一個很..."

2. 鏈式流式 API —— 打造領域專用語言

public static class QueryExtensions
{
    public static IQueryable WhereIf(this IQueryable q, bool cond, Expression> p)
        => cond ? q.Where(p) : q;
    
    public static IQueryable Page(this IQueryable q, int page, int size)
        => q.Skip((page-1)*size).Take(size);
}

// 用法:條件分頁查詢一氣呵成
var result = db.Users
    .WhereIf(activeOnly, u => u.IsActive)
    .WhereIf(!string.IsNullOrEmpty(keyword), u => u.Name.Contains(keyword))
    .Page(pageIndex, pageSize)
    .ToList();

3. 適配器模式 —— 統一異構介面

// 第三方庫類型不可修改
public class LegacyUser { public string FullName { get; set; } public int YearsOld { get; set; } }

// 擴展適配為統一介面
public static class LegacyAdapters
{
    public static UserDto ToDto(this LegacyUser u) 
        => new UserDto { Name = u.FullName, Age = u.YearsOld };
}

// 業務代碼無感知差異
var dto = legacyUser.ToDto();

命名空間組織最佳實踐

  • 通用基礎擴展放入 System 或 MyApp.Core.Extensions,專案級 using 全局可見
  • 領域專用擴展放入對應功能命名空間,按需引入
  • 避免在 System 下大量擴展,防止污染全局命名空間

總結

擴展方法是 C# 語法擴展性的里程碑,它將「為類型添加方法」從「修改類型定義」解耦出來。掌握優先級規則、善用鏈式模式、合理組織命名空間,能讓你構建出極具表達力的流式 API,讓代碼像讀英文一樣自然流暢。

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