.NET 8中循环构建动态LINQ查询触发数组越界,手动编写正常
问题原因及解决方法
问题原因
这是闭包捕获变量引用而非值导致的经典问题。在循环中构建LINQ Where条件时,lambda表达式捕获的是position变量本身的引用,而非循环当前迭代的position数值。当后续调用ToList()执行查询时,循环已执行完毕,position的值会变为model.ExactMatches.Count(即5),此时访问x.Word[position]会超出5个字符单词的有效索引范围(0-4),从而触发数组越界异常。
解决方法
有两种常见的修复方式,核心都是让lambda捕获当前迭代的固定值而非循环变量的引用:
方法1:循环内创建局部变量保存当前索引值
GetAllWords(); var model = await req.ReadFromJsonAsync<SearchModel>(); var query = AllWords.AsQueryable(); for (var position = 0; position < model.ExactMatches.Count; position++) { if (!string.IsNullOrWhiteSpace(model.ExactMatches[position])) { // 用局部变量捕获当前迭代的索引和目标字符 var currentPosition = position; var targetChar = model.ExactMatches[currentPosition]; Console.WriteLine($" {currentPosition} = {targetChar}"); query = query.Where(x => x.Word[currentPosition].ToString() == targetChar); } } var matches = query.ToList();
方法2:用foreach遍历带索引的集合项(更简洁)
GetAllWords(); var model = await req.ReadFromJsonAsync<SearchModel>(); var query = AllWords.AsQueryable(); // 过滤空项并同时获取索引与匹配字符 foreach (var (charMatch, position) in model.ExactMatches .Select((match, idx) => (match, idx)) .Where(item => !string.IsNullOrWhiteSpace(item.match))) { Console.WriteLine($" {position} = {charMatch}"); query = query.Where(x => x.Word[position].ToString() == charMatch); } var matches = query.ToList();
两种方法都能保证每个Where条件使用的是当前迭代的正确索引值,避免查询执行时出现索引越界。
内容的提问来源于stack exchange,提问作者Grandizer
相关产品推荐
相关产品推荐

