Ignoring for the moment the way that Linq can be processed by other query providers (e.g. against a database), in the example you link to we have two different approaches:
- First yield everything from the first enumeration, then yield everything from the second.
- Call the
Enumerable.Concat
method.
Well, what is Enumerable.Concat
? Since we're ignoring cases like Linq2SQL (which would likely turn concat into a UNION ALL
) what we care about here is the Linq2Objects implementation.
Now, there's more than one way to skin a concat, but the Mono source (for example) ends up calling a check and then into:
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;
}
In other words, the LINQ approach is the yield
approach.
Or if not, it might be something very similar. We could (if we liked typing more) implement it as the construction of an implementation of IEnumerator<TSource>
, but yield
saves us the hassle.
In all, LINQ is a bunch of handy tools that work well together. When they're the tool that works well, use them. When another tool works better, use it. When a LINQ-like tool would be nice, but it's not included in what you've got, write it yourself (just like we could do all the Linq2Objects stuff before Linq, which wasn't there for us in .NET2.0).