預設實作 IComparable<Employee> 只能有一種排序邏輯(如依 EmpID)。若需依「工齡」或其他欄位排序,必須引入 IComparer<T> 外部比較器。
public class Employee : IComparable<Employee> {
public int EmpID { get; set; }
public int CompareTo(Employee other) => this.EmpID.CompareTo(other.EmpID);
}
List<Employee>.Sort() 會自動呼叫此方法進行快速排序。
public enum ComparisonType { EmpID, YearsOfService }
public class EmployeeComparer : IComparer<Employee> {
public ComparisonType WhichComparison { get; set; }
public int Compare(Employee x, Employee y) =>
x.CompareTo(y, WhichComparison); // 委託給 Employee 多載
}
public int CompareTo(Employee other, ComparisonType type) {
return type == ComparisonType.EmpID
? this.EmpID.CompareTo(other.EmpID)
: this.YearsOfSvc.CompareTo(other.YearsOfSvc);
}
var cmp = Employee.GetComparer();
cmp.WhichComparison = ComparisonType.EmpID;
empList.Sort(cmp); // 依 ID 排序
cmp.WhichComparison = ComparisonType.YearsOfService;
empList.Sort(cmp); // 依工齡排序
// 原始隨機
ID: 103, Years: 11
ID: 108, Years: 15
ID: 107, Years: 14
ID: 108, Years: 5
ID: 102, Years: 0
// 依 EmpID
ID: 102, Years: 0
ID: 103, Years: 11
ID: 107, Years: 14
ID: 108, Years: 15
ID: 108, Years: 5
// 依 YearsOfService
ID: 102, Years: 0
ID: 108, Years: 5
ID: 103, Years: 11
ID: 107, Years: 14
ID: 108, Years: 15
此為策略模式在排序領域的經典應用:
IComparable = 內建預設策略IComparer = 外部可換裝策略ComparisonType = 策略參數化Comparer<T>.Create((x,y)=>…) 以 Lambda 簡寫比較器。IEnumerable<T>,亦可用 LINQ OrderBy/ThenBy 達成同樣效果且更具可讀性。