Search code examples
c#genericsvalue-typereference-typememorycache

Proper use of MemoryCache with generics?


I wish to use System.Runtime.Caching.MemoryCache but I'm wondering how to use it with generics.

In the following example, I would be in trouble if T is a value type.

public T GetItem<T>(string key, Func<T> loadItemFromDb)
{
    var cachedItem = (T) memoryCache.Get(key);
    if(cachedItem != null)
       return cachedItem;

    // call db
    //put result in cache
    // return result
}

MemoryCache.Get(string key) returns null if the cache entry identified by key doesn't exist and it would raise NullReferenceException as it tries to do (T)null (with T a value type)

How could I get similar behaviour for every T ?

EDIT : I removed where T : class as this constraint prevents the case I'm describing.

EDIT 2 : I add some code to provide intent


Solution

  • The problem is that the cast can fail if the value is null. So don't cast if the value is null.

    public T GetItem<T>(string key, Func<T> loadItemFromDb)
    {
        object cachedItem = memoryCache.Get(key);
        if (cachedItem is T)
           return (T)cachedItem;
        T item = loadItemFromDb();
        memoryCache.Add(key, item, somePolicy);
        return item;
    }
    

    There's no problem with value types here; if T is a value type, and cachedItem is not a boxed T, then we never cast cachedItem to T.

    FYI in C# 7 you can tighten that up a bit to:

        if (cachedItem is T t)
           return t;
    

    and now there's no cast at all!