【问题标题】:Why do I get: "iteration variable in a lambda expression may have unexpected results" [duplicate]为什么我会得到:“lambda 表达式中的迭代变量可能会产生意外结果” [重复]
【发布时间】:2012-03-01 21:03:17
【问题描述】:

可能重复:
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

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

【问题讨论】:

    标签: .net vb.net


    【解决方案1】:

    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/

    【讨论】:

    • 我们也能获得 C#3 和 C#4 编译器的补丁吗?我每天都会遇到这种情况,而我们公司现在才刚刚加入 C#4 的潮流。从字面上看,我等不及 C#5 了。
    • @JamesDunne,您确定您实际上是指 C# 版本而不是 .Net 版本吗?因为 C# 5 编译器可以针对例如 .Net 4.0,甚至更早的版本。
    • @svick:是的,编译器当然可以针对较旧的平台,但是当您希望 Visual Studio、一套 TFS 构建服务器以及您团队的所有编译器都是最新版本时,这无关紧要仍然针对较旧的平台。实际上,在旧的编译器版本上获得一个(希望是免费的)补丁比为了修复这个错误而购买整个套件的最新版本更容易也更便宜。
    • @JamesDunne:我们不打算默默地改变现有编译器的行为,不。对不起!
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-05
      • 1970-01-01
      • 2021-07-15
      • 2011-07-06
      • 1970-01-01
      • 2012-10-27
      • 1970-01-01
      相关资源
      最近更新 更多