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

C# 泛型進階:實作 IComparable 介面實現多欄位排序

     編輯:關於C語言

前言

在 C# 開發中,當我們需要對自訂物件集合進行排序時,實作 IComparable<T> 介面是最基礎的做法。但實務上常遇到需依據不同欄位排序的情況,例如員工資料既要按工號排序,也要按工齡排序。本文將透過完整範例,示範如何結合泛型與巢狀類別設計,實現靈活的多欄位排序機制。

核心設計:Employee 類別與 EmployeeComparer 巢狀類別

我們定義一個 Employee 類別,包含員工編號(empID)與工齡(yearsOfSvc)兩個屬性。關鍵在於實作 IComparable<Employee> 介面,並建立巢狀類別 EmployeeComparer 實作 IComparer<Employee>,透過列舉型別 ComparisonType 控制排序依據。

public class Employee : IComparable<Employee>
{
    private int empID;
    private int yearsOfSvc = 1;

    public Employee(int empID) { this.empID = empID; }
    public Employee(int empID, int yearsOfSvc) 
    { 
        this.empID = empID; 
        this.yearsOfSvc = yearsOfSvc; 
    }

    public override string ToString()
    {
        return $"ID:{empID}. Years of Svc:{yearsOfSvc}";
    }

    // 預設比較:依員工編號
    public int CompareTo(Employee rhs)
    {
        return this.empID.CompareTo(rhs.empID);
    }

    // 多欄位比較核心邏輯
    public int CompareTo(Employee rhs, EmployeeComparer.ComparisonType which)
    {
        switch (which)
        {
            case EmployeeComparer.ComparisonType.EmpID:
                return this.empID.CompareTo(rhs.empID);
            case EmployeeComparer.ComparisonType.Yrs:
                return this.yearsOfSvc.CompareTo(rhs.yearsOfSvc);
        }
        return 0;
    }

    // 取得比較器實例
    public static EmployeeComparer GetComparer()
    {
        return new EmployeeComparer();
    }

    // 巢狀比較器類別
    public class EmployeeComparer : IComparer<Employee>
    {
        private ComparisonType whichComparison;

        public enum ComparisonType { EmpID, Yrs }

        public ComparisonType WhichComparison
        {
            get { return whichComparison; }
            set { whichComparison = value; }
        }

        public int Compare(Employee lhs, Employee rhs)
        {
            return lhs.CompareTo(rhs, WhichComparison);
        }

        // 介面必要實作(簡化版)
        public bool Equals(Employee lhs, Employee rhs) => Compare(lhs, rhs) == 0;
        public int GetHashCode(Employee e) => e.GetHashCode();
    }
}

實際應用:測試排序功能

在 Tester 類別中,我們建立員工清單並展示三種狀態:原始順序、依工號排序、依工齡排序。

public class Tester
{
    static void Main()
    {
        List<Employee> empArray = new List<Employee>();
        Random r = new Random();
        
        // 產生 5 筆隨機測試資料
        for (int i = 0; i < 5; i++)
        {
            empArray.Add(new Employee(r.Next(10) + 100, r.Next(20)));
        }

        Console.WriteLine("=== 原始資料 ===");
        empArray.ForEach(e => Console.WriteLine(e));

        // 取得比較器並設定排序模式
        EmployeeComparer comparer = Employee.GetComparer();
        
        // 依員工編號排序
        comparer.WhichComparison = EmployeeComparer.ComparisonType.EmpID;
        empArray.Sort(comparer);
        Console.WriteLine("\n=== 依員工編號排序 ===");
        empArray.ForEach(e => Console.WriteLine(e));

        // 依工齡排序
        comparer.WhichComparison = EmployeeComparer.ComparisonType.Yrs;
        empArray.Sort(comparer);
        Console.WriteLine("\n=== 依工齡排序 ===");
        empArray.ForEach(e => Console.WriteLine(e));
    }
}

執行結果分析

=== 原始資料 ===
ID:103. Years of Svc:11
ID:108. Years of Svc:15
ID:107. Years of Svc:14
ID:108. Years of Svc:5
ID:102. Years of Svc:0

=== 依員工編號排序 ===
ID:102. Years of Svc:0
ID:103. Years of Svc:11
ID:107. Years of Svc:14
ID:108. Years of Svc:15
ID:108. Years of Svc:5

=== 依工齡排序 ===
ID:102. Years of Svc:0
ID:108. Years of Svc:5
ID:103. Years of Svc:11
ID:107. Years of Svc:14
ID:108. Years of Svc:15

結果清晰顯示:原始資料為隨機順序;第一次排序依 empID 遞增;第二次排序依 yearsOfSvc 遞增。注意員工編號 108 出現兩次,排序演算法保持穩定性。

設計重點總結

  • 封裝比較邏輯:將多欄位比較邏輯集中在 Employee.CompareTo(Employee, ComparisonType) 方法中,避免分散在各處。
  • 策略模式應用:EmployeeComparer 透過 WhichComparison 屬性動態切換排序策略,符合開放封閉原則。
  • 巢狀類別優勢:比較器緊密綁定於 Employee 類別,存取私有欄位無需公開屬性,提升封裝性。
  • 泛型類型安全:使用 IComparer<Employee> 避免 boxing/unboxing,效能優於非泛型版本。

延伸應用建議

若自行實作集合類別並需支援排序,建議加入泛型約束 where T : IComparable<T>,確保放入集合的型別皆可比較。此範例展示的模式廣泛適用於任何需要多欄位、可切換排序邏輯的業務場景。

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