c# 中无 comparator 类型,对应接口为 icomparer 和 icomparable;array.sort() 报错因元素未实现 icomparable 且未传 icomparer/comparison;自定义比较器须显式处理 null,返回值须为负数/0/正数,comparison 轻量但不可复用。

直接说结论:C# 里没有叫 Comparator 的类型,那是 Java 的;C# 对应的是 IComparer<t></t> 和 IComparable<t></t> ——用错接口或混淆泛型约束,排序会静默失败或抛 ArgumentException。
为什么 Array.Sort() 报 “At least one object must implement IComparable”?
这是最常踩的坑:传了普通对象数组(比如 Person[]),但 Person 类既没实现 IComparable<person></person>,也没提供外部 IComparer<person></person> 实例。
- 如果想让
Person自带默认排序逻辑(比如按Name升序),就在类里实现IComparable<person></person>,重写CompareTo() - 如果只是临时按年龄降序、或按多字段组合排,别改类,直接传一个
new PersonAgeComparer()或用Comparison<t></t>委托 -
Sort()方法重载很多,但只有Sort(T[], IComparer<t>)</t>和Sort(T[], Comparison<t>)</t>能绕过“必须实现IComparable”的检查
写 IComparer<t></t> 时最容易漏掉的 null 处理
自定义比较器里不处理 null,遇到集合中有 null 元素就会炸 —— 报 NullReferenceException,而不是你预想的“null 排最前/最后”。
正确做法是显式判断:
public int Compare(Person x, Person y)
{
if (x == null && y == null) return 0;
if (x == null) return -1; // null 排前面
if (y == null) return 1; // null 排后面
return string.Compare(x.Name, y.Name, StringComparison.Ordinal);
}
- 别依赖
string.Compare自动处理null:它只对字符串参数做空检查,不适用于外层对象 - 如果业务要求
null排最后,把-1和1对调即可 - 返回值必须严格是负数 / 0 / 正数,不能只写
return x.Age > y.Age;(这返回 bool)
Comparison<t></t> 比 IComparer<t></t> 更轻量,但有隐藏限制
用 lambda 写排序最简形式:Array.Sort(people, (a, b) => a.Age.CompareTo(b.Age)); —— 这背后用的是 Comparison<t></t> 委托,不是 IComparer<t></t>。
- 优势:不用单独写类,适合一次性逻辑;支持闭包(比如捕获当前
sortOrder变量) - 劣势:每次调用都新建委托实例,高频排序(如每帧调用)可能触发 GC;无法被多个地方复用,也不方便单元测试
- 注意:LINQ 的
OrderBy()接收的是Func<t tkey></t>,不是Comparison<t></t>,别混用
真正麻烦的不是写比较逻辑,而是搞清「谁负责判空」「谁控制 null 位置」「哪个重载走默认比较」「哪个强制要外部比较器」——这些边界一旦模糊,排序结果就不可控,而且很难 debug。











