LINQ与yield的比较

4
我几乎不使用“yield”运算符(我不讨厌它:))。如果可能,我更喜欢使用LINQ。
不管怎样,我10分钟前搜索了一些文章(您可以在下面的链接中找到),读了一下,并得到了一些想法:)
链接:rewrite-this-foreach-yield-to-a-linq-yield 想法:也许我不使用“yield”并不是很好。也许它比LINQ或其他一些优点更具有性能优势。
因此,我有一个问题,在上面的示例中哪种代码更“正确”(yield还是LINQ)(通常情况下)?
附言:我对可以使用LINQ而不是“yield”的情况很感兴趣。

4
它们两个都是正确的。你在问什么? - SLaks
1
我必须说实话...它们都很难调试 :-) (这是因为yield被转换为完全不同的代码,而LINQ本身就很难调试) - xanatos
当然,它们都是正确的...如果有一个是无效/不正确的,那我就不会问这个问题了 :) 实际上,我已经得到了我的问题的答案。感谢Jon Skeet。 - Maxim Polishchuk
3个回答

8
我认为在这种情况下使用LINQ更加清晰易懂。与“调用此方法,产生此结果”相比,它在更高的层次上运行-它描述了整体结果。
迭代器块非常有用,可以用于实现LINQ,无论是现有的操作符还是添加您自己的操作符。了解它们是值得的,但我不会担心您没有经常使用它们-这并不意味着代码质量不好或其他什么。

2
public static IEnumerable<Color> GetThemColors(){
     GetThePrimaryIds().Select(id=>yield return GetColorById(id));
     GetTheOtherIds().Select(id=>yield return GetOtherColorsById(id));
} 

这段代码无法正常工作。选择器是惰性的,而这些集合没有被枚举。


当然 - 编译器并不在意您是否想声明一些懒查询但不调用它们。 - Amy B
非常聪明!没想到这是可能的。 - Karel Frajták

1

暂且不考虑Linq可以通过其他查询提供程序(例如针对数据库)进行处理的方式,在您链接的示例中,我们有两种不同的方法:

  1. 首先从第一个枚举中产生所有内容,然后从第二个枚举中产生所有内容。
  2. 调用Enumerable.Concat方法。

那么,什么是Enumerable.Concat?由于我们忽略了像Linq2SQL这样的情况(可能会将concat转换为UNION ALL),因此我们在这里关心的是Linq2Objects实现。

现在,有多种方法可以连接,但Mono源代码(例如)最终会调用检查,然后进入:

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

换句话说,LINQ方法就是yield方法。

或者说,它可能非常相似。如果我们愿意打更多的字,我们可以将其实现为IEnumerator<TSource>的实现构造,但yield可以省去这些麻烦。

总的来说,LINQ是一堆方便的工具,它们很好地协同工作。当它们是适合的工具时,请使用它们。当另一个工具更好时,请使用它。当需要类似于LINQ的工具,但它没有包含在您拥有的内容中时,请自己编写它(就像我们在.NET2.0之前可以完成所有Linq2Objects的工作一样,因为那时还没有Linq)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接