Today I found some odd behavior when working with LINQ. It is hard to describe, so here is the code.
public void Foo(IEnumerable<string> strings) { IEnumberable<string> stringsInDb = strings.Where(s => this.QueryTheDbAndTakeALongTime(s)); foreach(string str in stringsInDb) { //Where clause in LINQ is actually executed } foreach(string str in stringsInDb) { //Where clause in LINQ is actually executed AGAIN } }
Luckily, some unit tests detected this behavior. It actually isn’t surprising when you think about it though. The proper thing to do for this case is actually call ToList() after the Where().
IEnumberable<string> stringsInDb = strings.Where(s => this.QueryTheDbAndTakeALongTime(s)).ToList();
Don’t let this behavior bite you.
This is because of deferred execution, and the fact that unless you call an enumerator, it will always re-execute the linq query. You can read more about this at:
Using LINQ to Convert an IENumerable to a List
Ya. A co-worker informed me of this behavior, which makes complete sense. It is just a little scary for the ignorant, because it allows code to be written that works yet behaves differently than might be expected.
LINQ….. *sigh*