【问题标题】:Assignment inside lambda expressionlambda 表达式内的赋值
【发布时间】:2014-03-17 15:35:31
【问题描述】:

我做了一个扩展,在 ObservableCollection 上添加了 ForEach() 方法:

public static void ForEach<T>(this ObservableCollection<T> enumerable, Action<T> action)
{
    foreach (var item in enumerable)
        action(item);
}

当我使用它时,像这样:

private bool Bar(int i)
{
    return i % 2 == 1;
}

private void Foo()
{
    Boolean ok = true;
    ObservableCollection<int> oc = new ObservableCollection<int> { 1, 2, 3, 4 };

    oc.ForEach(i => ok &= Bar(i));
    //ok is now false
}

我不明白ok 布尔值如何获取action(item) 执行的Bar() 方法返回的值?

【问题讨论】:

  • 因为它在本地范围内,并且您使用 &amp;= 分配它。
  • 您预计会发生什么? Lambda 捕获局部变量,因此它们存储对它们的引用并因此能够更改它们。
  • @AdamHouldsworth 谢谢,那是我不明白的。现在很清楚了。

标签: c# lambda expression


【解决方案1】:

允许 Lambda 修改其主体内代码范围内的变量。您需要对此类代码非常小心,因为您并不总是可以完全控制执行 lambdas 的时间。

例如,如果您将赋值添加到传递给延迟执行的方法的 lambda,则在该 lambda 的代码实际执行之前,该 lambda 的副作用(即赋值)将不可见。

这是一个例子:

bool ok = true;
IEnumerable<int> res = new[] {1, 2, 3}.Where(i => ok &= (i == 2));
// ok is true here
IList<int> listRes = res.ToList();
// ok is false here

如果您运行此代码,ok 将保持为true,即使源列表的第一项会触发将false 分配给ok 变量。但是,在您枚举 res 之前,这不会发生。

【讨论】:

  • 虽然这是真实且非常好的信息,但其中大部分不适用于此问题,因为foreach 未被延迟。这个答案非常有价值 - 我只是建议记下这一点。
  • @Magus 你是对的 - 与 OP 的问题相关的部分在第一句话中。但是,我想确保阅读此答案的人不会被新的令人兴奋的可能性所迷惑,因为需要小心处理。
【解决方案2】:

您正在应用 &= 这将和每个结果的 previos 值 ok (因为 ok 不是单个循环迭代的本地,它是在循环之外声明的)。换句话说,

因为条件仅对两个值(1 和 3)为真

ok = true && false && true && false

这是错误的。

【讨论】:

    猜你喜欢
    • 2011-09-11
    • 2021-09-01
    • 1970-01-01
    • 2017-04-21
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    相关资源
    最近更新 更多