c# - 使用 IComparable 和 IComparer 的多重排序规则?
问题描述
我是 C# 新手,只是关于如何正确使用 IComparable 和 IComparer 的问题。假设我们有以下类:
public class Student
{
int score;
string name;
}
我想先按 socre (desc) 排序,然后按 name (asc) 排序。
现在假设我无法访问 Student 类,所以我只能使用 IComparer 所以我必须创建一个帮助类(假设它称为 StudentComparer)并将相同的逻辑放入
public class StudentComparer: IComparer
{
int Compare(object o1, object o2)
{
Student s1 = o1 as Student;
Student s2 = o2 as Student;
// not checking null for simplicity
if (s1.score == s2.score)
return String.Compare(s1.name, s2.name);
else if (s1.score < s2.score)
return -1
else
return 1
}
}
这是我的问题,如果我以后只需要使用单个规则,例如,有时只按名称排序,有时只按分数排序。所以我必须创建另外两个实现 IComparer 的帮助类(ScoreComparer 和 NameComparer),它们在 StudentComparer 中有重复的代码为
public class ScoreComparer : IComparer
{
int Compare(object o1, object o2)
{
//half logic of StudentComparer
}
}
public class NameComparer: IComparer
{
int Compare(object o1, object o2)
{
//half logic of StudentComparer
}
}
我的案例很简单,想象一下如果有一个复杂的案例,每个比较器都包含数百行代码,那么如何避免重复代码?还是一种将多个比较器 A、B、C、D ... 组合成一个通用比较器的方法,以便它按顺序检查 A、B、C、D,就像 SQL 中的 order by 子句一样
解决方案
回到 linq 之前的日子,我经常使用比较器。
我处理不同排序选项的方法是在比较器实现的构造函数中指定这些选项,然后在Compare
方法中使用该信息。
幸运的是,我们现在有了 linq,所以整个事情可以用一行流畅的代码来完成:
// sortedStudents is an IEnumerable<Student> sorted by score and name.
var sortedStudents = students.OrderBy(s => s.Score).ThenBy(s => s.Name);
但是,如果由于某种原因您需要使用老式的方式,使用比较器和类似的东西,那么我将如何处理这个问题:
internal enum CompareBy
{
NameOnly,
ScoreAndName
}
public class StudentComparer: IComparer<Student>
{
private CompareBy _compareBy
public StudentComparer(CompareBy compareBy)
{
_compareBy = compareBy;
}
public int Compare(Student s1, Student s2)
{
// not checking null for simplicity
var nameCompare = string.Compare(s1.name, s2.name);
if(_compareBy == NameOnly)
{
return nameCompare;
}
// since there are only two members in the enum it's safe to write it like this.
// if the enum grows, you must change the code.
if (s1.score == s2.score)
{
return nameCompare;
}
else if (s1.score < s2.score)
{
return -1
}
return 1
}
}
推荐阅读
- javascript - Moment Js 我怎么知道我在目标时间的一个小时内?
- c# - “object”不包含“ElementExists”的定义
- css - 手机浏览器不支持字体
- javascript - Value.match(/[^0-9|\/]/gi) 不适用于数字?
- java - 无法从 mysql 获取数据以显示在我的 jList 中
- vba - 如何在不调用该列表的每个索引的情况下从下拉列表中选择 Vba?
- python - 如果用户没有输入可选值,如何通过表单(不是 django 表单)接收 django 视图中的可选值?
- java - 如何修复此错误?:线程“main”中的异常 java.lang.ArrayIndexOutOfBoundsException: 3
- amazon-web-services - AWS 上的弹性搜索服务。或者别的地方
- javascript - 将 div 与可点击翻转卡的底部对齐(引导程序 4)