循环使用PredicateBuilder报错,手动编写正常,求问题原因及解决方法
问题原因与解决方案
问题根源
你遇到的ArgumentOutOfRangeException是因为C#闭包对循环变量的引用捕获机制:循环里的i是同一个变量,你在Or方法里写的lambda表达式(y => y.Field<string>(sqlNames[i]) == filters[i][j])捕获的是i的引用,而非每次循环时i的当前值。当后续执行查询、解析谓词的时候,循环已经跑完,i的值变成了4(循环条件是i < 4,最后一次循环后i自增到4),此时访问sqlNames[4]或filters[4][0]自然超出数组索引范围。
而你手动写的代码用的是固定索引值(0、1、2、3),不存在变量引用捕获的问题,所以能正常运行。
修复代码
只需在循环内部把i的值复制到一个局部变量,让lambda捕获这个局部变量的值而非引用即可:
var outerPredicate = PredicateBuilder.New<DataRow>(); for (int i = 0; i < 4; i++) { // 关键:将当前循环的i值复制到局部变量 int currentI = i; var innerPredicate = PredicateBuilder.New<DataRow>(); for (int j = 0; j < 1; j++) { // 用currentI代替i innerPredicate = innerPredicate.Or(y => y.Field<string>(sqlNames[currentI]) == filters[currentI][j]); } outerPredicate = outerPredicate.And(innerPredicate); }
另外,你原代码中一开始声明的innerPredicate变量没有实际作用,直接在循环内部声明更简洁。
内容的提问来源于stack exchange,提问作者Bob Smith
相关产品推荐
相关产品推荐

