# ⚠️ Warning: Don't cache lazy IEnumerable<T> in .NET

(The same is true for `IAsyncEnumerable<T>`)

A few days ago I came across a code where a developer used .NET [MemoryCache](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.caching.memorycache) to cache data retrieved from the database. Sounds boring, but... every time the cache needed to return a result, a call to the database was made.

Let's take a look at a simplified example:

```csharp
var serviceProvider = new ServiceCollection().AddMemoryCache().BuildServiceProvider();
var randomizer = Random.Shared;
var memoryCache = serviceProvider.GetRequiredService<IMemoryCache>();

// NOTE: we cache the result of GetData()
var data1 = memoryCache.GetOrCreate("key", _ => GetDataFromDb()).ToList();
var data2 = memoryCache.GetOrCreate("key", _ => GetDataFromDb()).ToList();

IEnumerable<int> GetDataFromDb()
{
    // This method will be called twice!
    yield return randomizer.Next();
}
```

The problem here is that we cache not an array or collection as it may look at first glance, but a **lazy** `IEnumerable`, which is calculated not when we call the `GetDateFromDb()` method, but when we enumerate this lazy thing by calling `ToList()`.

As a result, the method `GetDataFromDb()` gets called twice (this is what we wanted to avoid with the help of the cache), and also `data1` and `data` will represent different lists with different values.

### Solution

Cache the actual result enumerated result instead of lazy `IEnumerable<T>`:

```csharp
var serviceProvider = new ServiceCollection().AddMemoryCache().BuildServiceProvider();
var randomizer = Random.Shared;
var memoryCache = serviceProvider.GetRequiredService<IMemoryCache>();

// NOTE: we cache GetData().ToList()
var data1 = memoryCache.GetOrCreate("key", _ => GetDataFromDb().ToList());
var data2 = memoryCache.GetOrCreate("key", _ => GetDataFromDb().ToList());

IEnumerable<int> GetDataFromDb()
{
    yield return randomizer.Next();
}
```

Now, the behavior will be as expected: the `GetDataFromDb()` method gets called only once and `data1` equals `data2`.

Thank you for reading and be careful with the cache.

Cheers!
