views:

93

answers:

4

I learned C# back in 2006, and recently tried to get back into it. I have learned then that they added something called LINQ Extensions to C#3.0. Now I am familiar with extension methods, and I'm just pondering the specifics of those related to IEnumerables.

Earlier today, me and one of my colleagues were debating whether or not the following blocks of code were equivalent:

List<int> integers;
IEnumerable<int> subResult = items.Where(i => IsPrime(i));
IEnumerable<int> orderedResult = subResult.OrderBy(i => i);

versus

List<int> integers;
IEnumerable<int> result = items.Where(i => IsPrime(i)).OrderBy(i => i);

He told me the latest was more efficient because the extension used late querying of it's source. I'm not quite sure I understood what he meant, and I was wondering if he was right.

+3  A: 

He's wrong.

The two block of code are identical.
In fact, if you don't use subResult anywhere else, they should compile to the exact same IL in release mode.

SLaks
+1  A: 

LINQ is implemented as extension methods on IEnumerable. You can think of working with LINQ queries as a 2-step process. First, you define the query and then you iterate over the query. Until the second step where you are actually iterating over the query, it hasn't executed yet.

Both examples are functionally equivalent and neither of them will actually execute the query until you iterate over the result, at which point both LINQ query operators (Where and OrderBy) will execute returning their appropriate enumerable result to the other and, ultimately, to the code performing the iteration.

Scott Dorman
+5  A: 

They're equivalent. They both use lazy evaluation / late querying.

What this means is that when the .Where method is called, it doesn't perform any actual enumeration of the list, it just keeps a reference to it's input and the condition it's going to check and stores those references. When the GetEnumerator method is later called on .Where's result, .Where kicks into action.

Same thing with .OrderBy. It doesn't actually do enumeration of the list until .GetEnumerator is called.

This stuff can be hard to understand but there's a few really good ways to learn about it. First is write up a simple example like you have, preferrably split onto multiple lines, with a simple for-each loop to iterate all the items. The debug the code and step through line-by-line. See how the debugger jumps around. It's very confusing at first, but run through a few times and you'll understand how lazy evaluation works.

Jon Skeet also has a wonderful demo for visualizing LINQ.

https://msmvps.com/blogs/jon_skeet/archive/2008/02/20/visual-linq-watch-query-expressions-as-they-happen.aspx

Sam
A: 

Deferred execution and Extension methods are totally seperate concepts.

Without extension method syntax:

var result = System.Linq.Enumerable.Where(
   myList, a => a.CustomerName == "Bob");

With extension methods, myList appears to have a Where method (it doesn't though).

var result = myList.Where(a => a.CustomerName == "Bob");
David B