HiveBrain v1.2.0
Get Started
← Back to all entries
principlecsharpMinor

Cache wrapper - Generics vs Dynamic

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
wrappercachegenericsdynamic

Problem

I've implemented a common wrapper pattern I've seen for the .NET cache class using generics as follows:

private static T CacheGet(Func refreashFunction, [CallerMemberName]string keyName = null)
{
    if (HttpRuntime.Cache[keyName] == null)
        HttpRuntime.Cache.Insert(keyName, refreashFunction(), null, DateTime.UtcNow.AddSeconds(600), System.Web.Caching.Cache.NoSlidingExpiration);
    return (T)HttpRuntime.Cache[keyName];
}


It could then be called like so:

public static Dictionary SomeCacheableProperty
{
    get
    {
        return CacheGet(() =>
        {
            Dictionary returnVal = AlotOfWork();
            return returnVal;
        });
    }
}


However, the CacheGet method could be implemented using dynamic:

private static dynamic CacheGet(Func refreashFunction, [CallerMemberName]string keyName = null)
{
    if (HttpRuntime.Cache[keyName] == null)
        HttpRuntime.Cache.Insert(keyName, refreashFunction(), null, DateTime.UtcNow.AddSeconds(600), System.Web.Caching.Cache.NoSlidingExpiration);
    return HttpRuntime.Cache[keyName];
}


The questions I have:

-
Is there a technically (or philosophically) superior preference between these two implementations?

-
Are these different at runtime?

-
If they are both left in, which one is being called in the getter method?

Solution

First of all, I think you misspelled refresh as refreash.

Second, your usage can probably be simplified

CacheGet(AlotOfWork);


Finally, you might want to check if refreshFunction returns null and maybe log a warning then as that function returning null would cause a cache miss every time.

Now to answer your specific questions.

-
I'll say it, the generic implementation is better. dynamic is a great trapdoor when you get really bogged down with generics or anonymous types and there's neat things you can do with it (see Dapper) but it still has some gotchas. For example, I do not think your function with dynamic will work in most cases.

HttpRuntime.Cache expects and returns object types meaning all types are being downcast or boxed. Therefore, if your function returns a User object, what is stored is still an object and what is returned from the cache is downcast likewise. Therefore your user.Username property will not be available until you cast, even though it's dynamic.

-
Yes. The generic version - with some subtle yet real differences - will run as if it was written for the type you're filling ` with. The dynamic version will just be a "value" and let the DLR figure out how to invoke members (which again, unless you're calling ToString() or GetHashCode(), will fail). dynamic` will also be slower as the runtime binding has to be done every time, though admittedly this is unlikely to be any sort of bottleneck.

-
Obviously I'm going to say always use the generic version in this case.

Code Snippets

CacheGet(AlotOfWork);

Context

StackExchange Code Review Q#41010, answer score: 4

Revisions (0)

No revisions yet.