【问题标题】:Access to Modified Closure in Lambda Expression访问 Lambda 表达式中的修改闭包
【发布时间】:2012-02-29 11:12:52
【问题描述】:
foreach(var category in categories) {
    a.AddRange(_db.Articles.Where(c => c.Categories.Contains(category)));
}

代码运行良好,但我收到一条关于“访问修改后的闭包”的警告,参考 lambda 表达式中使用的 category

问题:在这种情况下是否有任何后果的警告?

【问题讨论】:

  • this related question。它也可能有帮助。
  • 嗯,SO 中有十几个“Access to Modified Closure”命中,其中任何一个都回答了这个问题。
  • @RaymondChen 有,但他们没有解决 lambda 上下文是我问的唯一原因。我理解闭包的想法,只是想看看在这种奇怪的情况下它是否意味着在 LINQ 的上下文中更具体的东西。
  • c# 5 更改此行为以使类别变量具有当前迭代中的值而不是最后一个值。 iomagazine.com/Articles/2012/11/01/More-Than-Just-Async.aspx?Page=1

标签: c# linq lambda closures


【解决方案1】:

这里的警告是因为您正在访问 Where lambda 闭包内的变量 categorycategory 的值随着每次迭代而变化,Where 是延迟执行的,因此它将看到 category 的当前值与创建 lambda 时的值。

在这种情况下,您可能没问题。即使Where 被延迟评估,AddRange 方法也会提示并强制完成Where 的评估。因此Where 方法将看到它所期望的category 的值。

如果您想删除警告,只需声明迭代变量的本地副本并捕获它。

foreach(var category in categories) {
  var localCategory = category;
  a.AddRange(_db.Articles.Where(c => c.Categories.Contains(localCategory)));
}

【讨论】:

  • 我想这是我忘记了一些关于 foreach 循环的事情 - 迭代变量 category 在技术上是在循环之外吗?很像这个伪代码int i; for (i <= 10) { i++; }?如果是这种情况,我了解 - Where 可以在 category 更改后进行评估?我理解正确吗?
【解决方案2】:

它告诉您“类别”变量存在于闭包中,并且可以在您的 LINQ 表达式之外进行修改。

查看问题here 以获得一些解释。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 2011-07-28
    • 2010-09-23
    • 2015-11-08
    • 2013-09-21
    • 1970-01-01
    相关资源
    最近更新 更多