【问题标题】:Why use wrappers around the actual iterator functions in LINQ extension methods?为什么在 LINQ 扩展方法中使用实际迭代器函数的包装器?
【发布时间】:2017-03-30 10:42:24
【问题描述】:

在查看 Microsoft 对各种 C# LINQ 方法的实现时,我注意到公共扩展方法只是以单独的迭代器函数的形式返回实际实现的包装器。

例如(来自 System.Linq.Enumerable.cs):

public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
    if (first == null) throw Error.ArgumentNull("first");
    if (second == null) throw Error.ArgumentNull("second");
    return ConcatIterator<TSource>(first, second); 
}

static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second) { 
    foreach (TSource element in first) yield return element;
    foreach (TSource element in second) yield return element; 
}

是什么原因把迭代器这样包装,而不是把它们合二为一,直接返回迭代器?

像这样:

public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
    if (first == null) throw Error.ArgumentNull("first");
    if (second == null) throw Error.ArgumentNull("second");
    foreach (TSource element in first) yield return element;
    foreach (TSource element in second) yield return element; 
}

【问题讨论】:

标签: c# linq iterator


【解决方案1】:

包装器用于立即检查方法参数(即当您调用 LINQ 扩展方法时)。否则,在您开始使用迭代器之前不会检查参数(即在 foreach 循环中使用查询或调用一些执行查询的扩展方法 - ToList、Count 等)。此方法用于所有具有延迟执行类型的扩展方法。

如果您将使用不带包装器的方法,那么:

int[] first = { 1, 2, 3 };
int[] second = null;

var all = first.Concat(second); // note that query is not executed yet
// some other code
...
var name = Console.ReadLine();
Console.WriteLine($"Hello, {name}, we have {all.Count()} items!"); // boom! exception here

使用参数检查包装器方法,您将在first.Concat(second) 行获得异常。

【讨论】:

  • 非常有趣...直到您执行GetEnumerator().MoveNext() 才知道状态机没有启动...不清楚他们为什么做出这个决定...
  • @xanatos 在这种情况下,我们根本不会推迟执行 :)
  • @SergeyBerezovskiy 是的,你是对的......编译器无法区分要立即执行的“标头”和要延迟的“主体”。有一分钟我想“但它可以立即运行,然后在第一次产量之前停止”,但是执行(可能是查询)已经完成,只有值的返回会被推迟:-)
猜你喜欢
  • 2017-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-12
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
  • 2019-06-03
相关资源
最近更新 更多