Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

วิธีเรียงลำดับ List ของ Complex Types ด้วย Comparison Delegate ใน C#

Overloads ของเมธอด Sort() ในคลาส List คาดหวังให้ส่ง Comparison<T> Delegate เข้าไปเป็น Argument


public void Sort(Comparison comparison)

CompareTo คืนค่า Integer บ่งชี้ว่า Value ของ Instance นี้น้อยกว่า เท่ากับ หรือมากกว่า Value ของ Object ที่ระบุ

เมธอด Int16.CompareTo() ใน C# ใช้เปรียบเทียบ Instance นี้กับ Object ที่ระบุหรือ Int16 Instance อื่น

ตัวอย่าง: เรียงลำดับ Employee ตาม ID


using System;
using System.Collections.Generic;

class Program {
    public static void Main() {
        Employee employee1 = new Employee { ID = 101, Name = "Mark", Salary = 4000 };
        Employee employee2 = new Employee { ID = 103, Name = "John", Salary = 7000 };
        Employee employee3 = new Employee { ID = 102, Name = "Ken", Salary = 5500 };
        
        List listEmployees = new List {
            employee1, employee2, employee3
        };
        
        Console.WriteLine("Employees before sorting:");
        foreach (var emp in listEmployees) {
            Console.WriteLine(emp.ID);
        }
        
        // ใช้ Lambda Expression สำหรับ Comparison Delegate
        listEmployees.Sort((x, y) => x.ID.CompareTo(y.ID));
        
        Console.WriteLine("\nEmployees after sorting by ID:");
        foreach (var emp in listEmployees) {
            Console.WriteLine(emp.ID);
        }
        
        listEmployees.Reverse();
        
        Console.WriteLine("\nEmployees in descending order of ID:");
        foreach (var emp in listEmployees) {
            Console.WriteLine(emp.ID);
        }
    }
    
    // Approach 1: แยก Method (สำหรับ Logic ซับซ้อน/Reuse)
    private static int CompareEmployees(Employee c1, Employee c2) {
        return c1.ID.CompareTo(c2.ID);
    }
}

public class Employee {
    public int ID { get; set; }
    public string Name { get; set; }
    public int Salary { get; set; }
}

Output


Employees before sorting:
101
103
102

Employees after sorting by ID:
101
102
103

Employees in descending order of ID:
103
102
101

Comparison Delegate Patterns

1. Lambda Expression (Inline)


// Ascending
list.Sort((x, y) => x.ID.CompareTo(y.ID));

// Descending
list.Sort((x, y) => y.ID.CompareTo(x.ID));

// Multiple Criteria: Salary Desc, then Name Asc
list.Sort((x, y) => {
    int salaryCompare = y.Salary.CompareTo(x.Salary); // Desc
    if (salaryCompare != 0) return salaryCompare;
    return x.Name.CompareTo(y.Name); // Asc
});

2. Method Group (Named Method)


list.Sort(CompareEmployees); // Method Group Conversion

private static int CompareEmployees(Employee x, Employee y) {
    return x.ID.CompareTo(y.ID);
}

3. Comparer.Create (Factory)


var comparer = Comparer.Create((x, y) => x.ID.CompareTo(y.ID));
list.Sort(comparer);

4. IComparer Implementation (Reusable)


public class EmployeeSalaryComparer : IComparer {
    public int Compare(Employee x, Employee y) {
        if (x == null && y == null) return 0;
        if (x == null) return -1;
        if (y == null) return 1;
        return y.Salary.CompareTo(x.Salary); // Descending
    }
}

// Usage
list.Sort(new EmployeeSalaryComparer());

LINQ Alternative (Non-mutating)


// สร้าง List ใหม่ (ไม่ Mutate Original)
var sorted = listEmployees
    .OrderBy(e => e.ID)
    .ThenBy(e => e.Name)
    .ToList();

// Descending
var sortedDesc = listEmployees
    .OrderByDescending(e => e.Salary)
    .ThenBy(e => e.Name)
    .ToList();

Performance Comparison

MethodMutates OriginalMemorySpeed
List.Sort()YesO(1) ExtraFastest (In-place QuickSort)
LINQ OrderByNo (New List)O(n)Slower (Allocation)
Array.Sort()YesO(1) ExtraFast (Arrays)

Null Handling


// Null-safe Comparison
list.Sort((x, y) => {
    if (x == null && y == null) return 0;
    if (x == null) return -1;  // Nulls First
    if (y == null) return 1;
    return x.ID.CompareTo(y.ID);
});

// หรือใช้ Comparer.Default (Nulls First)
list.Sort(Comparer.Create((x, y) => 
    (x?.ID ?? -1).CompareTo(y?.ID ?? -1)));