C#中OrderByDescending 是LINQ扩展方法之一
·
一、OrderByDescending 简介
在 C# 中,OrderByDescending 是 LINQ 提供的一个扩展方法,用于对集合中的元素按指定字段进行降序排序。
它常用于:
- 排行榜系统
- 数据统计
- 商品价格排序
- UI列表展示
- 游戏分数排行
- 配置数据筛选
二、基本语法
// 基础版本
IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
带比较器版本:
// 自定义比较器版本
IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IComparer<TKey> comparer
)
三、参数说明
| 参数 | 说明 |
|---|---|
| source | 需要排序的集合 |
| keySelector | 排序依据字段 |
| comparer | 自定义比较规则 |
| 返回值 | 返回新的排序序列,不修改原集合 |
四、基础示例
1. 数字降序排序
using System;
using System.Linq;
using System.Collections.Generic;
var scores = new List<int>
{
95, 72, 88, 100, 64, 88
};
// 按数字降序排序
var sortedScores = scores.OrderByDescending(x => x);
Console.WriteLine(string.Join(", ", sortedScores));
// 输出:
// 100, 95, 88, 88, 72, 64
2. 字符串排序
按字母降序
var cities = new List<string>
{
"Tokyo",
"London",
"Paris",
"Singapore"
};
var sortedCities = cities
.OrderByDescending(x => x);
Console.WriteLine(string.Join(", ", sortedCities));
// 输出:
// Tokyo, Singapore, Paris, London
按字符串长度降序
var sortedByLength = cities
.OrderByDescending(x => x.Length);
Console.WriteLine(string.Join(", ", sortedByLength));
// 输出:
// Singapore, London, Tokyo, Paris
3. 自定义对象排序
public class Player
{
public string Name { get; set; }
public int Level { get; set; }
public int Score { get; set; }
public int Vip { get; set; }
}
var players = new List<Player>
{
new Player
{
Name = "Alex",
Level = 12,
Score = 950,
Vip = 1
},
new Player
{
Name = "Luna",
Level = 18,
Score = 1400,
Vip = 3
},
new Player
{
Name = "Mike",
Level = 9,
Score = 870,
Vip = 0
}
};
按等级降序
var byLevel = players
.OrderByDescending(p => p.Level);
foreach (var player in byLevel)
{
Console.WriteLine(
$"{player.Name} - Lv.{player.Level}"
);
}
// 输出:
// Luna - Lv.18
// Alex - Lv.12
// Mike - Lv.9
按分数降序
var byScore = players
.OrderByDescending(p => p.Score);
foreach (var player in byScore)
{
Console.WriteLine(
$"{player.Name} - {player.Score}"
);
}
// 输出:
// Luna - 1400
// Alex - 950
// Mike - 870
五、多条件排序
1. 主排序 + 次排序
先按分数降序,再按 VIP 等级降序:
var ranking = players
.OrderByDescending(p => p.Score)
.ThenByDescending(p => p.Vip);
foreach (var player in ranking)
{
Console.WriteLine(
$"{player.Name} - {player.Score} - VIP:{player.Vip}"
);
}
2. 错误示例
很多新人会这样写:
players
.OrderByDescending(p => p.Score)
.OrderBy(p => p.Name);
这是错误的。
因为第二个 OrderBy 会覆盖第一个排序。
正确写法应该使用:
.ThenBy()
或者:
.ThenByDescending()
六、结合其他 LINQ 操作
var topPlayers = players
.Where(p => p.Level >= 10) // 过滤
.OrderByDescending(p => p.Score) // 排序
.Select(p => new // 投影
{
p.Name,
p.Score
})
.Take(2); // 取前2个
foreach (var p in topPlayers)
{
Console.WriteLine(
$"{p.Name} - {p.Score}"
);
}
七、自定义比较器
忽略大小写排序:
var items = new List<string>
{
"apple",
"Banana",
"cherry",
"Date"
};
var result = items.OrderByDescending(
x => x,
StringComparer.OrdinalIgnoreCase
);
Console.WriteLine(string.Join(", ", result));
// 输出:
// Date, cherry, Banana, apple
八、空值处理
如果字段可能为 null:
var users = new List<string>
{
"Tom",
null,
"Alice",
"Bob"
};
var sorted = users
.OrderByDescending(x => x ?? "");
foreach (var item in sorted)
{
Console.WriteLine(item);
}
避免:
NullReferenceException
九、延迟执行(非常重要)
OrderByDescending 使用的是:
延迟执行(Deferred Execution)
真正排序是在遍历时执行。
var nums = new List<int>
{
1, 5, 3
};
var query = nums
.OrderByDescending(x => x);
nums.Add(100);
foreach (var n in query)
{
Console.WriteLine(n);
}
输出:
100
5
3
1
因为排序发生在 foreach 时,而不是创建 query 时。
十、不会修改原集合
很多新人容易误解:
var nums = new List<int>
{
3, 1, 2
};
nums.OrderByDescending(x => x);
Console.WriteLine(nums[0]);
输出:
3
原集合不会变化。
因为 LINQ 返回的是:
新的排序序列
正确写法:
nums = nums
.OrderByDescending(x => x)
.ToList();
十一、性能特点
1. 时间复杂度
通常为:
O(n log n)
2. 稳定排序
相同元素会保持原顺序。
var list = new[]
{
new { Name = "A", Score = 100 },
new { Name = "B", Score = 100 },
new { Name = "C", Score = 90 }
};
var result = list
.OrderByDescending(x => x.Score);
foreach (var item in result)
{
Console.WriteLine(item.Name);
}
输出:
A
B
C
A 和 B 的顺序不会改变。
3. LINQ 会产生 GC
在 Unity 中:
var result = players
.OrderByDescending(x => x.Score);
可能产生:
- 迭代器对象
- 临时数组
- GC Alloc
如果在:
- Update
- 战斗系统
- 实时排行榜
频繁调用,可能导致:
- GC Spike
- 卡顿
- 掉帧
十二、OrderByDescending 与 List.Sort 区别
1. OrderByDescending
| 特性 | 情况 |
|---|---|
| 修改原集合 | ❌ |
| 返回新序列 | ✅ |
| 延迟执行 | ✅ |
| 稳定排序 | ✅ |
| GC较多 | ✅ |
| 易读性高 | ✅ |
2. List.Sort
players.Sort(
(a, b) => b.Score.CompareTo(a.Score)
);
| 特性 | 情况 |
|---|---|
| 修改原集合 | ✅ |
| 返回新序列 | ❌ |
| 延迟执行 | ❌ |
| 稳定排序 | ❌ |
| GC较少 | ✅ |
| 性能更高 | ✅ |
十三、Unity 开发建议
1. 适合使用 LINQ 的场景
- 配置表
- 编辑器工具
- 一次性数据查询
- UI数据展示
- 后台统计
2. 不建议频繁使用 LINQ 的场景
- Update
- 战斗逻辑
- AI系统
- ECS
- 实时刷新排行榜
因为可能产生:
- GC
- 额外内存分配
- 性能问题
高频逻辑建议使用:
list.Sort()
十四、实际应用场景
1. 游戏排行榜
var leaderboard = players
.OrderByDescending(p => p.Score)
.Take(10);
2. 商品价格排序
var products = shopItems
.OrderByDescending(p => p.Price);
3. 获取经验值最高角色
var topRole = roles
.OrderByDescending(r => r.Exp)
.First();
十五、总结
OrderByDescending 的核心作用:
按指定字段生成一个新的降序排列序列
它:
- 不会修改原集合
- 支持链式调用
- 支持多条件排序
- 支持自定义比较器
- 可读性高
- 非常适合数据查询
但在 Unity 高频逻辑中,需要注意:
- GC
- 延迟执行
- 排序性能
很多情况下:
List.Sort()
会比 LINQ 更适合。
更多推荐

所有评论(0)