Matthew
Matthew

Reputation: 10444

How should I populate a MemoryCache without instantiating the object to be cached unneccesarily?

The MemoryCache class exposes a method called .AddOrGetExisting which is a threadsafe way to get if exists, and add if it doesn't exist.

This method returns NULL if the cached object didn't already exist. I think I understand the value of this because it provides feedback to the user regarding its existence in the cache.

My cache resolver looks like this:

private static T GetCachedCollection<T>(Guid cacheKey, Lazy<T> initializer)
{
    return (T) (MemoryCache.Default.AddOrGetExisting(cacheKey.ToString(), initializer.Value, _policy) ?? initializer.Value);
}

What I am trying to accomplish is that the object is not created unless it is needed, and if it is needed I don't want to construct it twice.

The concern I have is that when I pass the .Value of my Lazy type as a parameter it may invoke the initializer regardless of whether the item is found in cache or not. However, if I understand JIT properly it will pass the delegate of the method and not invoke it.

How should I accomplish these goals:

  1. Do not invoke the object initializer if it already exists in cache
  2. If it is not in the cache then invoke it only one time.

Upvotes: 4

Views: 1145

Answers (1)

Servy
Servy

Reputation: 203830

Don't store the object in the cache, store the Lazy.

private static T GetCachedCollection<T>(Guid cacheKey, Lazy<T> initializer)
{
    var cachedValue = (Lazy<T>)(MemoryCache.Default.AddOrGetExisting(
        cacheKey.ToString(), initializer, _policy) ?? initializer);
    return cachedValue.Value;
}

Upvotes: 7

Related Questions