✅ Caching an IEnumerable
Simple question: I have an
IEnumerable<T>
which does some complex-ish calculations, and I would ideally like to cache the result of the enumerable, but while still allowing it to be lazy and not use something like ToArray()
or ToList()
which would enumerate the entire thing at once. So for instance, if the enumerable produces some elements using a Select
, then if the user begins by enumerating the first three elements and nothing more, then those three elements would be cached and not be calculated again on successive enumerations. What would be the best way to do this?15 Replies
^ something like this
Isn't that what
yield
gives you ? Write a wrapper that enumerates the wrapped IEnumerable using yield
...
I haven't actually done this and maybe that's not actually easy to implement, but it sprang to mind...Idk what
yield
has to do with this. That's used to create iterator methods.Well, if you are using yield to yield up members of the source sequence it will remember where it left off and I was thinking you could have some state inside some wrapper that keeps yielding from wherever the wrapped thing was instead of starting a new enumeration...
Maybe it doesn't work, I didn't really think it through.
This looks like maybe it's in the ballpark of what you are thinking of?
https://github.com/dotnet/reactive/blob/main/Ix.NET/Source/System.Interactive/System/Linq/Operators/Memoize.cs
GitHub
reactive/Memoize.cs at main · dotnet/reactive
The Reactive Extensions for .NET. Contribute to dotnet/reactive development by creating an account on GitHub.
That
GetEnumerator_()
method is something else, but I think it's kind of what I had in mind...
https://github.com/dotnet/reactive/blob/85f1eb7c53e27cccdbeee3e0b044916168843fcc/Ix.NET/Source/System.Interactive/System/Linq/Operators/Memoize.cs#L170GitHub
reactive/Memoize.cs at 85f1eb7c53e27cccdbeee3e0b044916168843fcc · d...
The Reactive Extensions for .NET. Contribute to dotnet/reactive development by creating an account on GitHub.
Looks like what I had in mind
I was thinking of doing something similar, although just using a simple list instead of whatever an
IBuffer<T>
is.Give it a try, looks pretty nice to me...
ye
I wonder if I could use this
The implementation looks pretty straightforward, it's just the lock, exception handling, and stopping mechanisms which make it way less readable.
Also I don't really know what the difference between caching and memoization is
memoization just means not redoing something you've already computed. Same thing as caching I think, depending on what you mean by caching - caching might involve things like cache eviction, I don't think that's a thing in memoization?
i just use something like this
but that probably doesn't suit your needs
Okay I came up with this
It's really simple but it works
Closed!