前言
在編程過(guò)程中,我們?cè)谔幚韽?fù)雜的數(shù)據(jù)結(jié)構(gòu)或?qū)?xiàng)目列表進(jìn)行排序,需要用到對(duì)象的比較。在 C# 中,IComparer 與 IComparer<T> 提供了一種靈活而強(qiáng)大的方法來(lái)定義自定義比較邏輯,以便可以對(duì)它們進(jìn)行排序。它們功能上相似,只在使用泛型方面有所不同。本文我們探索如何有效地實(shí)現(xiàn)和使用它們。
IComparer
1、概述
IComparer 是用于定義比較兩個(gè)對(duì)象方法的接口,在默認(rèn)排序行為不能滿足我們的需求或需要根據(jù)自定義條件對(duì)對(duì)象進(jìn)行排序。它是在 Collections 命名空間中的,只由單個(gè)方法組成。
public interface IComparer
{
/// <summary>
/// 比較兩個(gè)對(duì)象 x 與 y
/// </summary>
/// <param name="x">對(duì)象 x </param>
/// <param name="y">對(duì)象 y </param>
/// <returns>
/// 如果 x 小于 y,則為負(fù)整數(shù)
/// 如果 x 大于 y,則為正整數(shù)
/// 如果 x 等于 y,則為零
/// </returns>
int Compare(object x, object y);
}
2、實(shí)現(xiàn)
實(shí)現(xiàn) IComparer,我們需要?jiǎng)?chuàng)建一個(gè)實(shí)現(xiàn)IComparer接口Compare方法的類(lèi)。根據(jù)需要進(jìn)行排序的自定義比較邏輯,實(shí)現(xiàn)該方法。下面通過(guò)示例(實(shí)現(xiàn)客戶集合按地區(qū)、再按名稱排序)探索如何實(shí)現(xiàn)和使用IComparer。
我們簡(jiǎn)化類(lèi)的定義,只包含編碼、名稱、地區(qū)與構(gòu)造方法。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;
}
}
}
實(shí)現(xiàn)接口的 Comparer方法, 定義按客戶的地區(qū)、名稱的比較邏輯。using System;
using System.Collections;
namespace Fountain.WinConsole.ComparerDemo
{
public class CustomerComparer : IComparer
{
/// <summary>
/// 比較兩個(gè)對(duì)象 x 與 y
/// </summary>
/// <param name="x">對(duì)象 x </param>
/// <param name="y">對(duì)象 y </param>
/// <returns></returns>
public int Compare(object x, object y)
{
if (x == null || y == null)
{
throw new ArgumentException("參數(shù)未引用實(shí)例");
}
// 對(duì)象 x 轉(zhuǎn)為 Customer
Customer customerx = x as Customer;
// 對(duì)象 x 轉(zhuǎn)為 Customer
Customer customery = y as Customer;
if (customerx == null || customery == null)
{
throw new ArgumentException("二個(gè)參數(shù)不是 Customer 類(lèi)型");
}
// 先比較城市
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 對(duì)客戶列表進(jìn)行排序,定義了客戶數(shù)組列表。
using System;
namespace Fountain.WinConsole.ComparerDemo
{
internal class Program
{
public static void Main()
{
// 創(chuàng)建客戶數(shù)組列表
var customers = new Customer[]
{
new Customer("Huawei", "華為","深圳"),
new Customer("Dajiang", "大疆", "深圳"),
new Customer("Guangqi", "廣汽", "廣州"),
new Customer("NanfangDiawang", "中國(guó)南方電網(wǎng)", "廣州"),
new Customer("Meidi", "美的", "佛山")
};
// 使用 CustomerComparer 對(duì)客戶列表進(jìn)行排序
Array.Sort(customers, new CustomerComparer());
Console.WriteLine("客戶排序按 城市 和 名稱排序");
foreach (var customer in customers)
{
// 出排序結(jié)果
Console.WriteLine($"{customer.City} {customer.Name}");
}
Console.ReadKey();
}
}
}
IComparer<T>
1、概述
IComparer<T> 是用于定義比較兩個(gè)對(duì)象方法的泛型接口,這個(gè)接口是在 System.Collections.Generic 命名空間中的,只由單個(gè)方法組成。
public interface IComparer<T>
{
/// <summary>
/// 比較兩個(gè)對(duì)象 x 與 y
/// </summary>
/// <param name="x">對(duì)象 x </param>
/// <param name="y">對(duì)象 y </param>
/// <returns>
/// 如果 x 小于 y,則為負(fù)整數(shù)
/// 如果 x 大于 y,則為正整數(shù)
/// 如果 x 等于 y,則為零
/// </returns>
int Compare(T x, T y);
}
2、實(shí)現(xiàn)
實(shí)現(xiàn) IComparer<T>,我們需要?jiǎng)?chuàng)建一個(gè)實(shí)現(xiàn)IComparer<T>接口Compare方法的類(lèi)。根據(jù)需要進(jìn)行排序的自定義比較邏輯,實(shí)現(xiàn)該方法。下面通過(guò)示例(實(shí)現(xiàn)客戶集合按地區(qū)、再按名稱排序)探索如何實(shí)現(xiàn)和使用IComparer<T>。
我們簡(jiǎn)化類(lèi)的定義,只包含編碼、名稱、地區(qū)與構(gòu)造方法。此類(lèi)已在上面示例給出。
實(shí)現(xiàn)接口的 Comparer方法, 定義按客戶的地區(qū)、名稱的比較邏輯。
using System;
using System.Collections.Generic;
namespace Fountain.WinConsole.ComparerDemo
{
public class CustomerComparer : IComparer<Customer>
{
/// <summary>
/// 比較兩個(gè)對(duì)象 x 與 y
/// </summary>
/// <param name="customerx">對(duì)象 x </param>
/// <param name="customery">對(duì)象 y </param>
/// <returns></returns>
public int Compare(Customer customerx, Customer customery)
{
if (customerx == null || customery == null)
{
throw new ArgumentException("二個(gè)參數(shù)不是 Customer 類(lèi)型");
}
// 先比較城市
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 對(duì)客戶列表進(jìn)行排序,定義客戶List列表。
using System;
using System.Collections.Generic;
namespace Fountain.WinConsole.ComparerDemo
{
internal class Program
{
public static void Main()
{
// 創(chuàng)建客戶數(shù)組列表
var customers = new Customer[]
{
new Customer("Huawei", "華為","深圳"),
new Customer("Dajiang", "大疆", "深圳"),
new Customer("Guangqi", "廣汽", "廣州"),
new Customer("NanfangDiawang", "中國(guó)南方電網(wǎng)", "廣州"),
new Customer("Meidi", "美的", "佛山")
};
// 使用 CustomerComparer 對(duì)客戶列表進(jìn)行排序
Array.Sort(customers, new CustomerComparer());
Console.WriteLine("客戶排序按 城市 和 名稱排序");
foreach (var customer in customers)
{
// 出排序結(jié)果
Console.WriteLine($"{customer.City} {customer.Name}");
}
// 創(chuàng)建客戶數(shù)組列表
var customerList = new List<Customer>
{
new Customer("Huawei", "華為","深圳"),
new Customer("Dajiang", "大疆", "深圳"),
new Customer("Guangqi", "廣汽", "廣州"),
new Customer("NanfangDiawang", "中國(guó)南方電網(wǎng)", "廣州"),
new Customer("Meidi", "美的", "佛山")
};
Console.WriteLine();
// 使用 CustomerComparer 對(duì)客戶列表進(jìn)行排序
customerList.Sort(new CustomerComparer());
Console.WriteLine("客戶排序按 城市 和 名稱排序");
foreach (var customer in customerList)
{
// 出排序結(jié)果
Console.WriteLine($"{customer.City} {customer.Name}");
}
Console.ReadKey();
}
}
}
優(yōu)點(diǎn)
小結(jié)
以上是 IComparer 和 IComparer<T> 在 C# 中,通過(guò)遵循分步實(shí)施示例,探索如何有效地實(shí)現(xiàn)和使用它們。通過(guò)分步實(shí)現(xiàn)的示例,我們可以輕松地將它們集成到項(xiàng)目中,并控制對(duì)象的排序和比較方式。
該文章在 2024/11/15 11:55:38 編輯過(guò)