Question

Do Linq methods on IEnumerable objects stack or do they override previous methods?

For example

string[] exampleArray = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
IEnumerable<string> iEnum1 = exampleArray.Skip(1); 
IEnumerable<string> iEnum2 = iEnum1.Take(5); 
IEnumerable<string> iEnum3 = iEnum2.Skip(1); 
IEnumerable<string> iEnum4 = iEnum3.Take(2); 
int count = iEnum4.Count(); 

Could I expect count to equal 2 and could I still expect iEnum3 to enumerate over "3", "4", "5", "6" if I wish to reuse that IEnumerable?

I'm trying to avoid creating new arrays even though they would be logically simpler to work with as the initial array will be relatively large already (from an even larger file stream).

Était-ce utile?

La solution

They do "stack" as you put it (typically referred to as "chaining").

Those LINQ statements (Take, Skip) are extensions of IEnumerable, and the end result will be that iEnum4 is exampleArray.Skip(1).Take(5).Skip(1).Take(2)

The final evaluation of that statement is deferred until certain methods are called (such as Count), at which time the LINQ statement is evaluated and the final result is stored in your int count variable.

Could I expect count to equal 2 and could I still expect iEnum3 to enumerate over "3", "4", "5", "6" if I wish to reuse that IEnumerable?

Yes, iEnum3 would evaluate whatever LINQ query it contained, such that iEnum3.Count() could evaluate to a different value than iEnum4.Count(). But if you call iEnum3.Count() three different times in your program, you might get three different results, because the evaluation is deferred and the values in exampleArray might have changed in the meantime.

Autres conseils

Yes count will equal 2. Let's break it down:

var iEnum1 = exampleArray.Skip(1); // { "2", "3", "4", "5", "6", "7", "8", "9" }
var iEnum2 = iEnum1.Take(5);       // { "2", "3", "4", "5", "6" }
var iEnum3 = iEnum2.Skip(1);       // { "3", "4", "5", "6" }
var iEnum4 = iEnum3.Take(2);       // { "3", "4" }
int count = iEnum4.Count();        // 2

And of course, you can chain these together like this:

int count = exampleArray.Skip(1).Take(5).Skip(1).Take(2).Count()

It's important to note, however, that Linq queries are lazy. Meaning they aren't actually evaluated until you iterate over the result set. The comments above only indicate what the variable would be, if you inspected the result set, but Linq doesn't actually produce that result until it needs it (for example, when you call Count). So while you can reuse iEnum3 in other Linq queries, it probably won't have any performance benefit—though it might promote code reuse / readability.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top