Enumerable.Range(,)生成超范围值求助:从List<T>随机选9项
排查你的Enumerable.Range索引越界问题
嘿,这个问题我之前帮朋友排查过类似的,核心是你对Enumerable.Range的参数理解有误!
问题根源
你可能误以为Enumerable.Range(start, end)是生成从start到end的整数,但实际上它的第二个参数是要生成的元素总数,正确的签名是Enumerable.Range(int start, int count)。
看你的代码:
var targetIndexes = Enumerable.Range(i + 1, sellableItems.Count-1) .OrderBy(x => random.Next()) .Take(9) .ToArray();
这段代码会生成从i+1开始的、一共sellableItems.Count-1个连续整数。举个实际的例子:如果i的值是5000,而sellableItems.Count是31(小型List的合理大小),那生成的最大数值就是5000+1 + 31-1 -1 = 5030——这正好是你遇到的超出范围的数值!
而sellableItems的有效索引范围是0到sellableItems.Count-1(比如30),当targetIndexes里出现5030这种远大于列表最大索引的数值时,后续访问sellableItems[targetIndexes[j]]自然会抛出索引越界异常。
另外,你的逻辑目标是从sellableItems中随机选9项(看起来还要排除索引i?),但当前代码生成的范围和列表的有效索引完全不匹配,这才是问题的核心。
正确的实现方式
根据你的需求(排除索引i,从剩余元素中随机选9项),可以这样修改代码:
// 先获取所有有效索引,排除不需要的i var validIndexes = Enumerable.Range(0, sellableItems.Count) .Where(idx => idx != i); // 打乱顺序后取最多9个 var targetIndexes = validIndexes.OrderBy(_ => random.Next()) .Take(9) .ToArray(); for (var j = 0; j < targetIndexes.Length; j++) { // 这里可以安全访问sellableItems[targetIndexes[j]] }
如果不需要排除索引i,直接简化成:
var targetIndexes = Enumerable.Range(0, sellableItems.Count) .OrderBy(_ => random.Next()) .Take(9) .ToArray();
小补充:如果sellableItems的元素总数本身小于9,Take(9)会自动返回所有元素,不会触发异常,这点可以放心。
内容的提问来源于stack exchange,提问作者Dongdong
相关产品推荐
相关产品推荐

