前言
在编程过程中,我们在处理复杂的数据结构或对项目列表进行排序,需要用到对象的比较。在 C# 中,IComparer 与 IComparer<T> 提供了一种灵活而强大的方法来定义自定义比较逻辑,以便可以对它们进行排序。它们功能上相似,只在使用泛型方面有所不同。本文我们探索如何有效地实现和使用它们。
IComparer
1、概述
IComparer 是用于定义比较两个对象方法的接口,在默认排序行为不能满足我们的需求或需要根据自定义条件对对象进行排序。它是在 Collections 命名空间中的,只由单个方法组成。
public interface IComparer{ /// <summary> /// 比较两个对象 x 与 y /// </summary> /// <param name="x">对象 x </param> /// <param name="y">对象 y </param> /// <returns> /// 如果 x 小于 y,则为负整数 /// 如果 x 大于 y,则为正整数 /// 如果 x 等于 y,则为零 /// </returns> int Compare(object x, object y);}
2、实现
实现 IComparer,我们需要创建一个实现IComparer接口Compare方法的类。根据需要进行排序的自定义比较逻辑,实现该方法。下面通过示例(实现客户集合按地区、再按名称排序)探索如何实现和使用IComparer。
我们简化类的定义,只包含编码、名称、地区与构造方法。namespace Fountain.WinConsole.ComparerDemo{ public class Customer { public string Code { get; set; } public string Name { get; set; } public string City { get; set; } /// <summary> /// /// </summary> /// <param name="code">编码</param> /// <param name="name">名称</param> /// <param name="city">城市</param> /// <returns></returns> public Customer(string code, string name, string city) { this.Code = code; this.Name = name; this.City = city; } }}
实现接口的 Comparer方法, 定义按客户的地区、名称的比较逻辑。using System;using System.Collections;
namespace Fountain.WinConsole.ComparerDemo{ public class CustomerComparer : IComparer { /// <summary> /// 比较两个对象 x 与 y /// </summary> /// <param name="x">对象 x </param> /// <param name="y">对象 y </param> /// <returns></returns> public int Compare(object x, object y) { if (x == null || y == null) { throw new ArgumentException("参数未引用实例"); } // 对象 x 转为 Customer Customer customerx = x as Customer; // 对象 x 转为 Customer Customer customery = y as Customer; if (customerx == null || customery == null) { throw new ArgumentException("二个参数不是 Customer 类型"); } // 先比较城市 int cityComparison = string.Compare(customerx.City, customery.City, StringComparison.OrdinalIgnoreCase); // 如果城市相等,则再比较名称 if (cityComparison == 0) { // 再比较名称 return string.Compare(customerx.Name, customery.Name, StringComparison.OrdinalIgnoreCase); } return cityComparison; } }}
使用 CustomerComparer 对客户列表进行排序,定义了客户数组列表。
using System;
namespace Fountain.WinConsole.ComparerDemo{ internal class Program { public static void Main() { // 创建客户数组列表 var customers = new Customer[] { new Customer("Huawei", "华为","深圳"), new Customer("Dajiang", "大疆", "深圳"), new Customer("Guangqi", "广汽", "广州"), new Customer("NanfangDiawang", "中国南方电网", "广州"), new Customer("Meidi", "美的", "佛山") };
// 使用 CustomerComparer 对客户列表进行排序 Array.Sort(customers, new CustomerComparer());
Console.WriteLine("客户排序按 城市 和 名称排序");
foreach (var customer in customers) { // 出排序结果 Console.WriteLine($"{customer.City} {customer.Name}"); } Console.ReadKey(); } }}

IComparer<T>
1、概述
IComparer<T> 是用于定义比较两个对象方法的泛型接口,这个接口是在 System.Collections.Generic 命名空间中的,只由单个方法组成。
public interface IComparer<T>{ /// <summary> /// 比较两个对象 x 与 y /// </summary> /// <param name="x">对象 x </param> /// <param name="y">对象 y </param> /// <returns> /// 如果 x 小于 y,则为负整数 /// 如果 x 大于 y,则为正整数 /// 如果 x 等于 y,则为零 /// </returns> int Compare(T x, T y);}
2、实现
实现 IComparer<T>,我们需要创建一个实现IComparer<T>接口Compare方法的类。根据需要进行排序的自定义比较逻辑,实现该方法。下面通过示例(实现客户集合按地区、再按名称排序)探索如何实现和使用IComparer<T>。
我们简化类的定义,只包含编码、名称、地区与构造方法。此类已在上面示例给出。
实现接口的 Comparer方法, 定义按客户的地区、名称的比较逻辑。
using System;using System.Collections.Generic;
namespace Fountain.WinConsole.ComparerDemo{ public class CustomerComparer : IComparer<Customer> { /// <summary> /// 比较两个对象 x 与 y /// </summary> /// <param name="customerx">对象 x </param> /// <param name="customery">对象 y </param> /// <returns></returns> public int Compare(Customer customerx, Customer customery) { if (customerx == null || customery == null) { throw new ArgumentException("二个参数不是 Customer 类型"); } // 先比较城市 int cityComparison = string.Compare(customerx.City, customery.City, StringComparison.OrdinalIgnoreCase); // 如果城市相等,则再比较名称 if (cityComparison == 0) { // 再比较名称 return string.Compare(customerx.Name, customery.Name, StringComparison.OrdinalIgnoreCase); } return cityComparison; } }}
使用 CustomerComparer 对客户列表进行排序,定义客户List列表。
using System;using System.Collections.Generic;
namespace Fountain.WinConsole.ComparerDemo{ internal class Program { public static void Main() { // 创建客户数组列表 var customers = new Customer[] { new Customer("Huawei", "华为","深圳"), new Customer("Dajiang", "大疆", "深圳"), new Customer("Guangqi", "广汽", "广州"), new Customer("NanfangDiawang", "中国南方电网", "广州"), new Customer("Meidi", "美的", "佛山") };
// 使用 CustomerComparer 对客户列表进行排序 Array.Sort(customers, new CustomerComparer());
Console.WriteLine("客户排序按 城市 和 名称排序");
foreach (var customer in customers) { // 出排序结果 Console.WriteLine($"{customer.City} {customer.Name}"); }
// 创建客户数组列表 var customerList = new List<Customer> { new Customer("Huawei", "华为","深圳"), new Customer("Dajiang", "大疆", "深圳"), new Customer("Guangqi", "广汽", "广州"), new Customer("NanfangDiawang", "中国南方电网", "广州"), new Customer("Meidi", "美的", "佛山") };
Console.WriteLine();
// 使用 CustomerComparer 对客户列表进行排序 customerList.Sort(new CustomerComparer()); Console.WriteLine("客户排序按 城市 和 名称排序");
foreach (var customer in customerList) { // 出排序结果 Console.WriteLine($"{customer.City} {customer.Name}"); } Console.ReadKey(); } }}

优点
小结
以上是 IComparer 和 IComparer<T> 在 C# 中,通过遵循分步实施示例,探索如何有效地实现和使用它们。通过分步实现的示例,我们可以轻松地将它们集成到项目中,并控制对象的排序和比较方式。
该文章在 2024/11/15 11:55:38 编辑过