简体   繁体   中英

Why does LINQ not cache enumerations?

So it is my understanding that LINQ does not execute everything immediately, it simply stores information to get at the data. So if you do a Where , nothing actually happens to the list, you just get an IEnumerable that has the information it needs to become the list.

One can 'collapse' this information to an actual list by calling ToList .

Now I am wondering, why would the LINQ team implement it like this? It is pretty easy to add a List at each step (or a Dictionary ) to cache the results that have already been calculated, so I guess there must be a good reason.

This can be checked by this code:

var list = Enumerable.Range(1, 10).Where(i => {
    Console.WriteLine("Enumerating: " + i);
    return true;
});

var list2 = list.All(i => {
    return true;
});

var list3 = list.Any(i => {
    return false;
});

If the cache were there, it would only output the Enumerating: i once for each number, it would get the items from the cache the second time.

Edit: Additional question, why does LINQ not include a cache option? Like .Cache() to cache the result of the previous enumerable?

It is pretty easy to add a List at each step

Yes, and very memory intensive. What if the data set contains 2 GB of data in total, and you have to store that in memory at once. If you iterate over it and fetch it in parts, you don't have a lot of memory pressure. When serializing 2 GB to memory you do, not to imagine what happens if every step will do the same...

You know your code and your specific use case, so only you as a developer can determine when it is useful to split off some iterations to memory. The framework can't know that.

Because it makes no sense, and if you would think about all the cases where it makes no sense you would not ask it. This is not so much a "does it sometimes make sense" question as a "are there side effects that make it bad". Next time you evaluate something like this, think about the negatives:

  • Memory consumption goes up as you HAVE to cache the results, even if not wanted.
  • On then ext run, the results may be different as incoming data may have changed. your simplistic example (Enumerable.Range) has no issue with that - but filtering a list of customers may have them updated.

Stuff like that makes is very hard to sensibly take away the choice from the developer. Want a buffer, make one (easily). But the side effects would be bad.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM