C# foreach循环中内置的Linq查询总是从上一次迭代中获取参数值

C# foreach循环中内置的Linq查询总是从上一次迭代中获取参数值,c#,linq,C#,Linq,我有一个包含几个关键字的列表。 我通过他们像这样构建我的linq查询(归结为消除代码噪音): List keys=FillKeys() foreach(字符串键入键){ q=q.Where(c=>c.Company.Name.Contains(key)); } 当我现在使我的键包含两个单独返回结果的键,但不能同时出现(q中的每个项不是“xyz”就是“123”,不是“123”就是“xyz”),我仍然会得到结果。结果集与它得到的最后一个字符串相同 我看了一下linq查询,它似乎创建了正确的sql,

我有一个包含几个关键字的列表。 我通过他们像这样构建我的linq查询(归结为消除代码噪音):

List keys=FillKeys()
foreach(字符串键入键){
q=q.Where(c=>c.Company.Name.Contains(key));
}
当我现在使我的键包含两个单独返回结果的键,但不能同时出现(q中的每个项不是“xyz”就是“123”,不是“123”就是“xyz”),我仍然会得到结果。结果集与它得到的最后一个字符串相同

我看了一下linq查询,它似乎创建了正确的sql,但它用相同的(最后一个)值替换了@p1和@p2


我做错了什么?

在lambda表达式中重复使用了相同的变量(
key

有关更多详细信息,请参阅我的文章,还有一些相关的SO问题:

简单的解决方法是首先复制变量:

List<string> keys = FillKeys()
foreach (string key in keys){
    string copy = key;
    q = q.Where(c => c.Company.Name.Contains(copy));
}
List keys=FillKeys()
foreach(字符串键入键){
字符串副本=键;
q=q.Where(c=>c.Company.Name.Contains(copy));
}

可能是捕获的变量问题;尝试添加:

List<string> keys = FillKeys()
foreach (string key in keys){
    string tmp = key;
    q = q.Where(c => c.Company.Name.Contains(tmp));
}
List keys=FillKeys()
foreach(字符串键入键){
字符串tmp=键;
q=q.Where(c=>c.Company.Name.Contains(tmp));
}
它在C#5.0中已经修复,上面在C#5.0中的示例可以工作,但在早期版本的C#中失败

但要小心,这与for循环无关

  static void Main()
        {
            IEnumerable<char> query = "aaa bbb ccc";
            string lettersToRemove = "ab";

            Console.WriteLine("\nOK with foreach:");
            foreach (var item in lettersToRemove)
            {
                query = query.Where(c => c != item);   
            }   
            foreach (char c in query) Console.Write(c);

            //OK:
            Console.WriteLine("\nOK with foreach and local temp variable:");
            query = "aaa bbb ccc";

            foreach (var item in lettersToRemove)
            {
                var tmp = item;
                query = query.Where(c => c != tmp);
            }            
            foreach (char c in query) Console.Write(c);


            /*
             An IndexOutOfRangeException is thrown because:
             firstly compiler iterates the for loop treating i as an outsite declared variable  
             when the query is finnaly invoked the same variable of i is captured (lettersToRemove[i] equals 3) which generates IndexOutOfRangeException

             The following program writes aaa ccc instead of writing ccc:
             Each iteration gets the same variable="C", i (last one frome abc). 
             */

            //Console.WriteLine("\nNOK with for loop and without temp variable:");
            //query = "aaa bbb ccc";

            //for (int i = 0; i <  lettersToRemove.Length; i++)
            //{
            //    query = query.Where(c => c != lettersToRemove[i]);
            //}
            //foreach (char c in query) Console.Write(c);

            /*
             OK
             The solution is to assign the iteration variable to a local variable scoped inside the loop
             This causes the closure to capture a different variable on each iteration.
            */
            Console.WriteLine("\nOK with for loop and with temp variable:");
            query = "aaa bbb ccc";

            for (int i = 0; i < lettersToRemove.Length; i++)
            {
                var tmp = lettersToRemove[i];
                query = query.Where(c => c != tmp);
            }
            foreach (char c in query) Console.Write(c);
        } 
static void Main()
{
IEnumerable query=“aaa bbb ccc”;
字符串lettersToRemove=“ab”;
Console.WriteLine(“\nOK加foreach:”);
foreach(lettersToRemove中的var项目)
{
query=query.Where(c=>c!=项);
}   
foreach(查询中的字符c)控制台;
//好:
Console.WriteLine(“\nOK带foreach和本地温度变量:”);
query=“aaa bbb ccc”;
foreach(lettersToRemove中的var项目)
{
var tmp=项目;
query=query.Where(c=>c!=tmp);
}            
foreach(查询中的字符c)控制台;
/*
引发IndexOutOfRangeException是因为:
首先,编译器迭代for循环,将i视为外部声明变量
当最终调用查询时,将捕获相同的变量i(lettersToRemove[i]等于3),该变量将生成IndexOutOfRangeException
以下程序写入aaa ccc,而不是写入ccc:
每次迭代都会得到相同的变量=“C”,i(最后一个变量来自e abc)。
*/
//Console.WriteLine(“\n带for循环且不带临时变量的OK:”);
//query=“aaa bbb ccc”;
//对于(int i=0;ic!=lettersToRemove[i]);
//}
//foreach(查询中的字符c)控制台;
/*
好啊
解决方案是将迭代变量分配给循环内的局部变量
这会导致闭包在每次迭代中捕获不同的变量。
*/
Console.WriteLine(“\nOK,带for循环和temp变量:”);
query=“aaa bbb ccc”;
对于(int i=0;ic!=tmp);
}
foreach(查询中的字符c)控制台;
} 

Hehe,同时发现了这一点:你很容易(但获得了)学分;)谢谢基本上和双向飞碟相同,但我只能指定一个解决方案。虽然有点,没问题。我感到欣慰的是,我们给出了同样的答复-不可复制的
  static void Main()
        {
            IEnumerable<char> query = "aaa bbb ccc";
            string lettersToRemove = "ab";

            Console.WriteLine("\nOK with foreach:");
            foreach (var item in lettersToRemove)
            {
                query = query.Where(c => c != item);   
            }   
            foreach (char c in query) Console.Write(c);

            //OK:
            Console.WriteLine("\nOK with foreach and local temp variable:");
            query = "aaa bbb ccc";

            foreach (var item in lettersToRemove)
            {
                var tmp = item;
                query = query.Where(c => c != tmp);
            }            
            foreach (char c in query) Console.Write(c);


            /*
             An IndexOutOfRangeException is thrown because:
             firstly compiler iterates the for loop treating i as an outsite declared variable  
             when the query is finnaly invoked the same variable of i is captured (lettersToRemove[i] equals 3) which generates IndexOutOfRangeException

             The following program writes aaa ccc instead of writing ccc:
             Each iteration gets the same variable="C", i (last one frome abc). 
             */

            //Console.WriteLine("\nNOK with for loop and without temp variable:");
            //query = "aaa bbb ccc";

            //for (int i = 0; i <  lettersToRemove.Length; i++)
            //{
            //    query = query.Where(c => c != lettersToRemove[i]);
            //}
            //foreach (char c in query) Console.Write(c);

            /*
             OK
             The solution is to assign the iteration variable to a local variable scoped inside the loop
             This causes the closure to capture a different variable on each iteration.
            */
            Console.WriteLine("\nOK with for loop and with temp variable:");
            query = "aaa bbb ccc";

            for (int i = 0; i < lettersToRemove.Length; i++)
            {
                var tmp = lettersToRemove[i];
                query = query.Where(c => c != tmp);
            }
            foreach (char c in query) Console.Write(c);
        }