为什么foreach中需要的临时变量被包含在lambda表达式中?

问题描述:

我读C# 4 in a Nutshell,我已经走到这一段代码:为什么foreach中需要的临时变量被包含在lambda表达式中?

IQueryable<Product> SearchProducts (params string[] keywords) 
{ 
    IQueryable<Product> query = dataContext.Products; 

    foreach (string keyword in keywords) 
    { 
    string temp = keyword; 
    query = query.Where (p => p.Description.Contains (temp)); 
    } 
    return query; 
} 

右键有一个“警告”说是这样的代码之后:

The temporary variable in the loop is required to avoid the outer variable trap, where the same variable is captured for each iteration of the foreach loop.

我不吨得到它,我不明白为什么temp变量是必要的。什么是outter variable trap

来源:http://www.albahari.com/nutshell/predicatebuilder.aspx

可有人请澄清这一点?

+4

你一定要阅读[这篇文章](http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx )。 – 2012-03-24 22:03:15

+0

看到这个:http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx – Phil 2012-03-24 22:03:39

+0

每个人都提出了相同的博客文章,如何来之前我从来没有听说过Eric?谢谢所有 – sebagomez 2012-03-24 22:08:39

因为只有一个被称为keyword的变量已关闭。然而,临时变量不同每次迭代。

因此,没有临时变量,当λ为后执行,keyword评估为它在循环中分配的最后一个值。

另一种解决方案,在某些情况下,是强制评估(并最终与List等)。

+0

'以后',这是关键字!我没有看到,谢谢! – sebagomez 2012-03-24 22:05:55

问题是keyword正在改变。 =>代表关闭当前变量的值,而不是创建委托时过去返回的值。 Eric Lippert's blog post有详细的解释。

这经典的C bug是同样的错误:

#include <stdio.h> 
#include <pthread.h> 

void * MyThreadFunction(void *x) 
{ 
    printf("I am thread %d\n", * (int *) x); 
    return NULL; 
} 

int main(void) 
{ 
    int i; 
    pthread_t t[10]; 
    void *ret; 
    for(i=0; i<10; i++) 
     pthread_create(&t[i], NULL, MyThreadFunction, (void *) &i); 
    for(i=0; i<10; i++) 
     pthread_join(t[i], &ret); 
} 

* (int *) x得到当前i,还不时创建的线程的值。

+0

这是一篇不错的文章,但它让我很烦恼没有一个小的摘要/摘要可以在最小的上下文中使用它:( – 2012-03-24 22:08:35