为什么我会得到:“lambda表达式中的迭代变量可能会产生意外结果”

时间:2012-03-01 21:03:17

标签: .net vb.net

  

可能重复:
  Why is it bad to use a iteration variable in a lambda expression

为什么我会得到:“lambda表达式中的迭代变量可能会产生意外结果”?假设我有以下代码:

  Dim writeAbleColumns As String() = {"IsSelected", "IsFeeExpense", "IsSubscriptionRedemption"}
  With grid
     For Each column As DataGridViewColumn In .Columns
      column.ReadOnly = Not Array.Exists(writeAbleColumns, Function(arrElement) column.Name = arrElement)
      Next
  End With

我收到警告:

Warning 1   Using the iteration variable in a lambda expression may have unexpected results.  Instead, create a local variable within the loop and assign it the value of the iteration variable.

我不明白为什么将我的代码更改为以下内容会改变:

  Dim writeAbleColumns As String() = {"IsSelected", "IsFeeExpense", "IsSubscriptionRedemption"}
  With grid
     For Each column As DataGridViewColumn In .Columns
      Dim c As DataGridViewColumn = column
      column.ReadOnly = Not Array.Exists(writeAbleColumns, Function(arrElement) c.Name = arrElement)
      Next
  End With

除警告消失外,基本上没有任何变化。我只有另一个变量指向我的变量。为什么警告?可能会发生什么意外的事情?

2 个答案:

答案 0 :(得分:15)

lambda绑定到变量,而不是变量在lambda变为委托时的值。当循环变量更新时,绑定到该变量的每个lambda 也会看到变量的值,您可能不需要它。每次迭代循环时创建一个新变量会将每个lambda绑定到一个新的,不同的,不变的变量上。

这是C#和VB的一个主要难点。 在C#5和VB 11中,我们正在改变循环闭包语义以缓解此问题。

有关详细信息,请参阅

Is there a reason for C#'s reuse of the variable in a foreach?

以及蒂姆的文章的最后几段:

http://msdn.microsoft.com/en-us/magazine/cc163362.aspx

和我的文章:

http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/

答案 1 :(得分:4)

在你的情况下,什么都不会出错。

问题是如果lambda在循环继续后被保存并使用(例如,在事件处理程序中使用)。 Eric Lippert has a very nice explanation on his blog

哦,this question已经在SO上有很长的参考列表。