从 C# 基础到掌握 — 第 6 集
使用集合和 LINQ 操作数据
该博客上撰写的文章是出于教学目的而创建的。 另外,文章中的信息可能不正确,请谨慎。
游戏和应用程序存储、搜索和排序大量数据。 根据目的选择集合并使用 LINQ 表达处理意图将导致更清晰的流程而不是更短的代码。
选择收藏
var party = new List<Player>();
var itemById = new Dictionary<int, Item>();
var unlockedIds = new HashSet<int>();
itemById.Add(10, new Item(10, "Potion"));
unlockedIds.Add(10);
List适合有序列表,Dictionary适合key查找,HashSet适合判断值是否存在并防止重复。 如果用索引器读取字典中没有的key,就会出现异常,所以可以使用TryGetValue。
使用 LINQ 查询
List<Monster> targets = monsters
.Where(monster => monster.IsAlive)
.OrderBy(monster => monster.Health)
.Take(3)
.ToList();
选择三个生命值较低的活体怪物的意图从计算顺序中就可见一斑。 LINQ 创建新的结果流,而不自动修改原始集合。
延迟执行
IEnumerable<Monster> alive = monsters.Where(monster => monster.IsAlive);
monsters.Add(new Monster());
foreach (Monster monster in alive)
{
Console.WriteLine(monster.Health);
}
Where返回的查询通常在遍历时执行。 如果中间原来的改变了,结果也可能会改变。要修复当前结果,请立即使用 ToList() 进行计算。
检查经常性费用
LINQ 调用不一定很慢,但它们可以创建迭代器、委托和结果集合。 对于每帧执行数千次的路径,简单循环和缓冲区重用可能更合适。
targets.Clear();
foreach (Monster monster in monsters)
{
if (monster.IsAlive)
{
targets.Add(monster);
}
}
最好首先创建一个易于阅读的查询,并仅更改在实际测量中发现问题的部分。 集合和 LINQ 的关键不是拥有最短的语法,而是明确存储数据的目的以及何时处理它。