如何使用 C# 中的比较委托对复杂类型列表进行排序?

1. 引言

在 C# 中,我们常常需要对列表进行排序。对于简单类型,我们可以通过调用默认的比较方法(如 int.CompareTo())来实现排序。但是对于复杂类型,我们需要自定义比较方法。这就涉及到了委托的应用。本文将介绍如何使用 C# 中的比较委托对复杂类型列表进行排序。

2. 简单类型排序介绍

首先,我们来回顾一下对简单类型的排序方法。以 int 类型为例:

int[] numbers = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 };

Array.Sort(numbers);

这段代码创建了一个整数数组,并使用了内置的 Array.Sort() 方法对数组进行排序。在排序的过程中,我们并没有指定比较方法,因为默认情况下,Sort() 方法会使用整数类型的默认比较方法 int.CompareTo() 进行排序。

3. 复杂类型排序介绍

3.1 对象列表排序

当我们需要对对象列表进行排序时,我们需要自定义比较方法。比如,下面的代码创建了一个 Person 类,并创建了一个 Person 类型的列表:

class Person

{

public string Name { get; set; }

public int Age { get; set: }

public double Height { get; set; }

}

List people = new List()

{

new Person() { Name = "Alice", Age = 25, Height = 1.65 },

new Person() { Name = "Bob", Age = 30, Height = 1.75 },

new Person() { Name = "Charlie", Age = 20, Height = 1.80 },

};

如果我们要按照年龄进行排序,我们可以编写如下的比较方法:

int CompareByAge(Person x, Person y)

{

return x.Age.CompareTo(y.Age);

}

然后,我们可以使用列表的 Sort() 方法进行排序:

people.Sort(CompareByAge);

此时,列表会按照年龄的顺序进行排序。

3.2 复杂类型嵌套排序

当我们需要对内部具有多个字段的复杂类型进行排序时,我们可以定义一个委托,将排序条件表示为委托。例如:

delegate TKey KeySelector<TKey, TValue>(TValue value);

这个委托表示一个键选择器,它使用一个值作为参数,并返回该值的键。

假设我们有一个 Person 类型的列表,每个人有一个 LastName 字段和一个 FirstName 字段。我们可以使用下面的委托将委托定义为根据姓和名进行排序:

KeySelector<string, Person> byFirstName = p => p.FirstName;

KeySelector<string, Person> byLastName = p => p.LastName;

现在,我们要按照姓和名字对人员进行排序,我们可以使用 List<T>.Sort() 重载方法,它接受一个比较器委托作为参数。以下是一个使用上述键选择器的示例:

people.Sort((x, y) => byLastName(x).CompareTo(byLastName(y)) != 0

? byLastName(x).CompareTo(byLastName(y))

: byFirstName(x).CompareTo(byFirstName(y)));

上面的代码比较复杂,但它的逻辑很清晰。它首先比较姓氏,如果两个姓氏相同,则比较名字。由于选定的值和排序条件均由委托确定,因此此方法可以扩展到任意类型的排序。

4. 使用比较委托进行排序

4.1 排序委托

为了使用比较委托排序,我们需要定义一个委托类型。在以下示例中,我们定义一个名为 Comparison<T> 的通用委托类型,它需要两个类型为 T 的参数,并返回一个 int 类型的值:

delegate int Comparison<T>(T x, T y);

此委托表示一个比较函数,其参数为两个值和一个结果,结果的符号表示两个参数的相对顺序。

4.2 委托使用

现在,我们可以使用 Comparison<T> 委托进行排序。

以下是一个使用比较委托进行排序的示例,它在 Person 类型的列表中使用委托对人年龄进行排序:

List<Person> people = new List<Person>()

{

new Person() { Name = "Alice", Age = 25, Height = 1.65 },

new Person() { Name = "Bob", Age = 30, Height = 1.75 },

new Person() { Name = "Charlie", Age = 20, Height = 1.80 },

};

Comparison<Person> compareAge = (x, y) => x.Age.CompareTo(y.Age);

people.Sort(compareAge);

在上面的示例中,我们首先创建了一个 Person 类型的列表。然后,我们定义了一个比较委托,该委托将比较人的年龄。最后,我们使用 List<T>.Sort() 方法并传递比较委托来对列表进行排序。

4.3 按多个字段排序

为了按多个字段排序,我们可以向比较委托添加一些额外的比较条件。以下是对类型为 Person 的列表按姓和名进行排序的示例:

Comparison<Person> compareName = (x, y) => x.LastName.CompareTo(y.LastName) != 0

? x.LastName.CompareTo(y.LastName)

: x.FirstName.CompareTo(y.FirstName);

people.Sort(compareName);

在上面的示例中,我们首先定义了一个比较条件,将比较人的姓和名。然后,我们使用 List<T>.Sort() 方法并传递比较委托来对列表进行排序。

5. 总结

本文介绍了如何使用 C# 中的比较委托对复杂类型列表进行排序。我们首先回顾了对简单类型的排序方法,然后介绍了如何对复杂类型进行排序。最后,我们介绍了如何使用比较委托进行排序,并讨论了如何使用比较委托对多个字段进行排序。

后端开发标签