创建对象时需要考虑是否实现比较器
1、基础
有对象的地方,一般都会存在比较。在此根据一个Salary列表实现对象比较的例子。Salary类需要实现接口IComparable。
class Salary:IComparable { public string Name { get; set; } public int BaseSalary { get; set; } public int Bonus { get; set; } public int CompareTo(object obj) { Salary salary = obj is Salary ? obj as Salary : null; if(salary==null) { throw new Exception("类型不同,无法比较"); } if(BaseSalary>salary.BaseSalary) { return 1; } else if(BaseSalary==salary.BaseSalary) { return 0; } else { return -1; } //以上代码可有以下代码代替,使用整型默认比较方法 //return BaseSalary.CompareTo(salary.BaseSalary); } }
实现接口IComparable后,可以根据BaseSalary对Salary集合对象排序。在Main函数中代码如下:
public static void Main() { ArrayList companySalary = new ArrayList(); companySalary.Add(new Salary() { Name = "Mike", BaseSalary = 3000,Bonus=1000 }); companySalary.Add(new Salary() { Name = "Rose", BaseSalary = 2000, Bonus = 6000 }); companySalary.Add(new Salary() { Name = "Tom", BaseSalary = 5000, Bonus = 5000 }); companySalary.Add(new Salary() { Name = "Jeffry", BaseSalary = 1000, Bonus = 2000 }); companySalary.Add(new Salary() { Name = "Steve", BaseSalary = 4500, Bonus = 1900 }); companySalary.Sort(); foreach (Salary salary in companySalary) { Console.WriteLine("{0}\t BaseSalary: {1}\tBonus: {2}", salary.Name, salary.BaseSalary,salary.Bonus); } }
但是,此处实现相当于比较局限,局限与只能使用BaseSalary排序,不能使用其他方式排序。如果使用Bonus进行排序,就需要改变源码。接口IComparer的作用可以避免这类问题。
2、IComparer接口
使用IComparer接口实现一个自定义比较器:
class BonusComparer : IComparer { int IComparer.Compare(object x, object y) { Salary salary1 = x is Salary ? x as Salary : null; Salary salary2 = y is Salary ? y as Salary : null; return salary1.Bonus.CompareTo(salary2.Bonus); } }
在主控端调用时排序时,需要在Sort方法中传入一个实现了IComparer接口的比较器对象:companySalary.Sort(new BonusComparer())。以此实现可以根据需要,实现多种比较。
3、泛型实现
在前面,使用了性能不高的ArrayList类。在泛型出来之后,需要尽量使用泛型集合。在CompareTo和Compare和函数中,需要对对象进行转型,比较影响性能,尤其是对大型集合进行排序时,性能影响非常明显。而泛型的出现,可以避免运行时的转型。因此,上面的代码全部更换为泛型类型:
class Program { public static void Main() { List<Salary> companySalary = new List<Salary>(); companySalary.Add(new Salary() { Name = "Mike", BaseSalary = 3000, Bonus = 1000 }); companySalary.Add(new Salary() { Name = "Rose", BaseSalary = 2000, Bonus = 6000 }); companySalary.Add(new Salary() { Name = "Tom", BaseSalary = 5000, Bonus = 5000 }); companySalary.Add(new Salary() { Name = "Jeffry", BaseSalary = 1000, Bonus = 2000 }); companySalary.Add(new Salary() { Name = "Steve", BaseSalary = 4500, Bonus = 1900 }); companySalary.Sort(); foreach (Salary salary in companySalary) { Console.WriteLine("{0}\t BaseSalary: {1}\tBonus: {2}", salary.Name, salary.BaseSalary, salary.Bonus); } companySalary.Sort(new BonusComparer());//提供一个默认比较器 foreach (Salary salary in companySalary) { Console.WriteLine("{0}\t BaseSalary: {1}\tBonus: {2}", salary.Name, salary.BaseSalary, salary.Bonus); } } } class Salary : IComparable<Salary> { public string Name { get; set; } public int BaseSalary { get; set; } public int Bonus { get; set; } public int CompareTo(Salary other) { if (other == null) { throw new Exception("类型不同,无法比较"); } if (BaseSalary > other.BaseSalary) { return 1; } else if (BaseSalary == other.BaseSalary) { return 0; } else { return -1; } //以上代码可有以下代码代替,使用整型默认比较方法 //return BaseSalary.CompareTo(other.BaseSalary); } } class BonusComparer : IComparer<Salary> { public int Compare(Salary x, Salary y) { return x.Bonus.CompareTo(y.Bonus); } }
4、Linq实现
针对前面实现排序方法时,需要实现多个接口,新增了方法使得代码入侵性太高。可扩展性差,对于有新的排序要求,就必须实现新的比较器。使用Linq,可以实现遍历、筛选、投影集合等功能。
class Program { public static void Main() { List<Salary> companySalary = new List<Salary>(); companySalary.Add(new Salary() { Name = "Mike", BaseSalary = 3000, Bonus = 1000 }); companySalary.Add(new Salary() { Name = "Rose", BaseSalary = 2000, Bonus = 6000 }); companySalary.Add(new Salary() { Name = "Tom", BaseSalary = 5000, Bonus = 5000 }); companySalary.Add(new Salary() { Name = "Jeffry", BaseSalary = 1000, Bonus = 2000 }); companySalary.Add(new Salary() { Name = "Steve", BaseSalary = 4500, Bonus = 1900 }); var baseSalarySort = from salary in companySalary orderby salary.BaseSalary select salary; foreach (Salary salary in baseSalarySort) { Console.WriteLine("{0}\t BaseSalary: {1}\tBonus: {2}", salary.Name, salary.BaseSalary, salary.Bonus); } var bonusSort = from salary in companySalary orderby salary.Bonus select salary; foreach (Salary salary in bonusSort) { Console.WriteLine("{0}\t BaseSalary: {1}\tBonus: {2}", salary.Name, salary.BaseSalary, salary.Bonus); } } } class Salary { public string Name { get; set; } public int BaseSalary { get; set; } public int Bonus { get; set; } }
Linq可以带来很大的便利性,但需要掌握比较器、迭代器、索引器的原理,以便更好地理解Linq的思想。
凡所有相,皆是虚妄。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?