views:

85

answers:

3

What is Linq actually doing?

+6  A: 

(I'm assuming this is for LINQ to Objects. Anything else will be implemented differently :)

It's just returning everything from the first, and then everything from the second. All data is streamed. Something like this:

public static IEnumerable<T> Concat(this IEnumerable<T> source1,
    IEnumerable<T> source2)
{
    if (source1 == null)
    {
        throw new ArgumentNullException("source1");
    }
    if (source2 == null)
    {
        throw new ArgumentNullException("source1");
    }
    return ConcatImpl(source1, source2);
}


private static IEnumerable<T> ConcatImpl(this IEnumerable<T> source1,
    IEnumerable<T> source2)
{
    foreach (T item in source1)
    {
        yield return item;
    }
    foreach (T item in source2)
    {
        yield return item;
    }
}

I've split this into two methods so that the argument validation can be performed eagerly but I can still use an iterator block. (No code within an iterator block is executed until the first call to MoveNext() on the result.)

Jon Skeet
@Jon: I'm not sure I completely understand your comment: exactly what would be different if it was all in one method?
Steven Sudit
how fast you are answering? grate ...
anishmarokey
@Steven: Concat gets called when the LINQ expression is created (because of `return`). ConcatImpl gets called when the LINQ expression is evaluated (because of `yield return`). @Jon: I love SO, but boy are you fast. Maybe I'll only try to answer when it's 3am your time. :)
Stephen Cleary
@Stephen: Ok, just to make sure I got this right, you're saying that ConcatImpl immediately returns an iterator block without executing anything until MoveNext is called (by foreach), while Concat executes immediately, allowing the parameters to be checked now instead of later. Right?
Steven Sudit
@Steven: Spot on. Note that ConcatImpl should have been private, which it now is.
Jon Skeet
Note that this has performance implications; the naive implementation of Concat is not optimized for the case of composition of concatenations. See http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx for an analysis of the performance of naively composed concatenations.
Eric Lippert
@Stephen: Jon might not be in the time zone you think he is. :-)
Eric Lippert
@Eric: I stand by the theory that Jon is an AI. Thanks for the interesting link.
Steven Sudit
@Eric: I want my own time zone that travels with me wherever I go... and the only time is coffee time.
Jon Skeet
CST - Coffee Standard Time!Naturally, there is no CDT, because the caffeine makes daylight savings irrelevant.
Steven Sudit
+1  A: 

It enumerates each collection in turn, and yields each element. Something like that :

public static IEnumerable<T> Concat<T>(this IEnumerable<T> source, IEnumerable<T> other)
{
    foreach(var item in source) yield return item;
    foreach(var item in other) yield return item;
}

(if you look at the actual implementation using Reflector, you will see that the iterator is actually implemented in a separate method)

Thomas Levesque
+1  A: 

It depends on the LINQ provider you are using. LinqToSql or L2E might use a database UNION, whereas LINQ to Objects might just enumerate both collections for your in turn.

tster