如何使用C# Linq为满足条件的对象列表添加元素?代码待修正
问题分析与修复方案
首先咱们拆解你代码里的两个核心问题:
1. Linq查询的误用导致编译错误
你写的Players.Where(p => p.Id == winnerId).Select(p => p.SetPoints).Add(winnerPoints); 是行不通的——因为Where和Select返回的都是只读的IEnumerable序列,不是可直接修改的集合,自然没有Add方法。而且Select之后你得到的是一堆List<int>的序列,就算能调用Add,也不是你想要的给单个玩家加分数的逻辑。
2. 随机选胜者的逻辑有问题
Tournament.Random.Next(0, 1) 这个调用只会返回0,因为Random.Next(minValue, maxValue)是左闭右开的区间——它生成的数大于等于minValue,小于maxValue。如果你的Players列表里有多个玩家,你应该写成Tournament.Random.Next(0, Players.Count),这样才能随机选中任意一个玩家。
正确的实现代码
下面是修改后的Simulate方法,我会逐行解释逻辑:
public void Simulate() { var winnerPoints = 6; var looserPoints = Tournament.Random.Next(0, 5); // 修正:随机从所有玩家里选胜者,适配任意数量的玩家 var winnerIndex = Tournament.Random.Next(0, Players.Count); var winner = Players[winnerIndex]; // 找到败者:如果是2个玩家的场景,直接取另一个;玩家数量更多可调整逻辑 var looser = Players.First(p => p.Id != winner.Id); // 直接操作找到的玩家对象,给他们的分数列表加值 winner.SetPoints.Add(winnerPoints); looser.SetPoints.Add(looserPoints); }
如果你更倾向于用Linq通过Id查找玩家(比如Id是唯一标识的场景),可以这样写:
public void Simulate() { var winnerPoints = 6; var looserPoints = Tournament.Random.Next(0, 5); // 先随机选一个玩家的Id作为胜者Id var winnerId = Players[Tournament.Random.Next(0, Players.Count)].Id; // 用SingleOrDefault找到对应玩家(Id唯一的话用Single更严谨) var winner = Players.SingleOrDefault(p => p.Id == winnerId); // 必须检查是否找到玩家,避免空引用异常 if (winner != null) { winner.SetPoints.Add(winnerPoints); // 同样处理败者 var looser = Players.SingleOrDefault(p => p.Id != winnerId); if (looser != null) { looser.SetPoints.Add(looserPoints); } } }
额外注意事项
- 务必确保
Player类的SetPoints已经初始化!比如在Player的构造函数里加上SetPoints = new List<int>();,否则会抛出NullReferenceException。 - 如果你的玩家数量可能超过2个,败者的选择逻辑需要调整——比如随机选另一个玩家,或者根据赛事规则确定败者。
内容的提问来源于stack exchange,提问作者Mike Hawkins
相关产品推荐
相关产品推荐

