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

C# 擴展方法進階實戰:改良 ScottGu 的 In 擴展

     編輯:關於C#

前言

ScottGu 早期示範的 In 擴展方法雖展示擴展語法,但實用性有限。本文逐步改良:params 簡化呼叫 → 泛型約束保證型別安全,打造生產級 In 擴展。

原版回顧


// ScottGu 原版
public static bool In(this object o, IEnumerable c)
{
    foreach (object i in c)
        if (i.Equals(o)) return true;
    return false;
}

// 呼叫麻煩:需顯式建立陣列/集合
bool b = 1.In(new int[] { 1, 2, 3 });
bool b = "Tom".In(new string[] { "Bob", "Kitty", "Tom" });

改良一:params 關鍵字簡化參數


public static bool In(this object o, params object[] values)
{
    foreach (var v in values)
        if (v.Equals(o)) return true;
    return false;
}

// 呼叫簡潔許多
bool b1 = 1.In(1, 2, 3, 4, 5);
bool b2 = "Tom".In("Bob", "Kitty", "Tom", "Jim");

改良二:泛型約束確保型別安全


// 隱患:object 參數允許混合型別,編譯通過但邏輯錯誤
string name = "App1";
bool dangerous = "Tom".In("Bob", "Kitty", name, 3); // 不小心多打逗號,3 為 int

// 解決:泛型約束強制型別一致
public static bool In<T>(this T source, params T[] values)
{
    return values.Any(v => v.Equals(source));
}

// 現在編譯器會攔截型別不匹配
// "Tom".In("Bob", "Kitty", 3); // 編譯錯誤:無法從 int 轉換為 string

進階優化:效能與邊界處理


public static class InExtensions
{
    // 基礎版:適用小型陣列
    public static bool In<T>(this T source, params T[] values)
        => values?.Any(v => EqualityComparer<T>.Default.Equals(v, source)) ?? false;

    // 大集合優化:轉為 HashSet O(1) 查找
    public static bool In<T>(this T source, IEnumerable<T> values)
    {
        if (values == null) return false;
        // 閾值可調整,如 > 50 元素改用 HashSet
        return values is ICollection<T> coll && coll.Count > 50
            ? new HashSet<T>(values).Contains(source)
            : values.Contains(source);
    }

    // 支援自訂比較器
    public static bool In<T>(this T source, IEqualityComparer<T> comparer, params T[] values)
        => values?.Any(v => comparer.Equals(v, source)) ?? false;
}

使用範例


// 基本用法
if (status.In(Status.Active, Status.Pending)) DoWork();

// 字串比較忽略大小寫
if (userInput.In(StringComparer.OrdinalIgnoreCase, "yes", "y", "ok")) Confirm();

// 搭配列舉
if (dayInWeek.In(DayOfWeek.Saturday, DayOfWeek.Sunday)) IsWeekend();

// 數值範圍檢查 (配合 C# 8 範圍運算子)
if (score.In(Enumerable.Range(60, 41).ToArray())) IsPass(); // 60~100

對比總結

版本呼叫語法型別安全效能適用場景
原版new[] { ... }無 (object)O(n)示範用
Params1, 2, 3無 (object)O(n)快速原型
泛型1, 2, 3編譯期保證O(n)一般業務
優化版集合/陣列編譯期保證O(1) 大集合高頻/大數據

結語

從 object 到泛型、從陣列到 IEnumerable、從線性搜尋到 HashSet 優化,In 擴展的演進過程完美詮釋了「深入想一步」的工程思維:語法糖要好吃,更要營養安全。建議將優化版收納於專案共用庫,替代冗長的 || 判斷鏈。

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