【问题标题】:Is there really multiple iterations of an IEnumerable in this code?这段代码中真的有 IEnumerable 的多次迭代吗?
【发布时间】:2017-05-18 12:04:03
【问题描述】:
    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        foreach (var element in source) action(element);
        return source;
    }

上面的代码给了我一个警告,说源代码可能会被迭代多次,但真的是这样吗?在foreach语句中迭代了一次,但是return语句如何让它再次迭代呢?

【问题讨论】:

  • 从某种意义上说,因为你将它返回给调用者,调用者可以用IEnumerable做什么?只能再列举一遍。就像myList.ForEach(c =&gt; DoStuff(c)).ToArray()
  • 是否可以在可枚举的元素上延迟执行?

标签: c# linq ienumerable


【解决方案1】:

返回不会再次迭代可枚举。但是您正在返回它,并且由于您可以对这个结果做任何事情的唯一方法是在其他地方迭代它,所以会给出这个警告。

如果您以后不打算迭代它,为什么要返回它?

【讨论】:

  • 是的,它将被重新迭代。我想要 ForEach 的 Linq 版本,这样我就可以做类似 list.ForEach(x=>x.Number++).Where(x=>x.Number > 3).Etc...
  • 只使用选择。例如:list.Select(x => x++).Where(x => x > 3)
【解决方案2】:

在您显示的当前代码中,只有一次迭代。您很可能在其他地方再次枚举它,因为返回了相同的枚举。这就是警告告诉你的。

我个人的偏好是将ForEach 的返回类型更改为void,并添加第二个返回Func&lt;T, R&gt; 的结果。

所以:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    foreach (var element in source)
        action(element);
}

还有:

public static IEnumerable<R> ForEach<T, R>(this IEnumerable<T> source, Func<T, R> action)
{
    foreach (var element in source)
        yield return action(element);
}

这样你就不会意外地重用同一个可枚举并且你让它变得懒惰:它不会在你真正调用可枚举之前执行。

【讨论】:

  • 第二个应该可以;但是,它可能“可能”违反了 OP 的类型约束。
  • 这是为什么呢? @AlyEl-Haddad
  • 因为在他的方法中,他保证返回的IEnumerable的类型与源的类型相同。这里,返回的IEnumerable '可能' 的类型因函数参数而异;这就是为什么我说“可能”。 @Patrick Hofman
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 2011-10-31
  • 2018-12-06
  • 1970-01-01
相关资源
最近更新 更多