降序排列应使用sort()配合y.compareto(x)比较器或orderbydescending(),reverse()仅翻转顺序而非排序;前者就地修改且高效,后者返回新序列更安全但有性能开销。

用 Sort() 配合比较器实现降序排列
直接调用 List<t>.Sort()</t> 默认是升序,要倒序得显式传入比较逻辑。最常用的是用 Comparison<t></t> 委托或 IComparer<t></t> 实现类。
常见错误是写成 x.CompareTo(y) 却忘了交换顺序——那还是升序。降序必须是 y.CompareTo(x) 或取反。
-
list.Sort((a, b) => b.CompareTo(a));—— 适用于实现了IComparable的类型(如int、string) -
list.Sort((a, b) => -a.Length.CompareTo(b.Length));—— 按字符串长度降序,注意负号位置不能错 - 对自定义类,别直接用
CompareTo,应明确字段比较:list.Sort((x, y) => y.Score.CompareTo(x.Score));
用 OrderByDescending() 更安全但不就地修改
OrderByDescending() 属于 LINQ,返回新序列,原列表不变。适合“查”而非“改”,也避免副作用。
性能上它会创建新枚举器和临时数组,大数据量时比 Sort() 多一次遍历和内存分配;但代码可读性高,且线程更友好(不改原集合)。
-
var sorted = list.OrderByDescending(x => x.Name).ToList();—— 必须加.ToList()才得到新List<t></t> - 若后续还要继续链式操作(比如
Where+Take),直接用IEnumerable<t></t>更省内存 - 注意:
OrderByDescending每次调用都重新排序,别在循环里反复调用
Reverse() 不是排序,只是翻转现有顺序
这是最大误区:Reverse() 不比较元素值,只按当前索引倒过来排。如果列表本来没排过序,Reverse() 后也不是“倒序排列”,只是把插入顺序反过来。
典型误用场景:先 AddRange 一堆数据,再 Reverse(),以为得到了降序结果——其实只是把添加顺序颠倒了。
-
list.Reverse();是就地翻转,返回void(注意不是返回新集合) -
list.AsEnumerable().Reverse()返回新枚举器,原列表不变 - 真正需要降序时,务必先
Sort()或OrderByDescending(),再考虑是否需要Reverse()
泛型约束和 null 值处理容易出错
用 CompareTo 时,如果 T 可能为 null(比如 List<string></string>),直接调用会抛 NullReferenceException。
OrderByDescending 内部用的是 Comparer<t>.Default</t>,对 null 有默认行为(null 排最前),但自定义比较器必须自己处理。
- 安全写法:
(a, b) => (b ?? string.Empty).CompareTo(a ?? string.Empty) - 或者用空合并 + 条件判断:
(a, b) => a == null ? (b == null ? 0 : 1) : (b == null ? -1 : b.CompareTo(a)) - 若类型未实现
IComparable<t></t>,Sort()会报ArgumentException,编译期不报错,运行才崩
null,以及有没有现成的比较逻辑。多数业务场景下,OrderByDescending 最省心;高频写入+就地修改时,Sort 更高效;而 Reverse 真的只是翻转,别指望它替你排序。











