0

I'm working with a library which contains some 'cacheHelper' functions which act as a wrapper for bits of the System.Runtime.Caching namespace.

For example:

public bool IsInCache(string keyname){
    return MemoryCache[keyname] != null;
}

public static void SaveToCache(string cacheKey, object savedItem, 
                               DateTime absoluteExpiration)
{
    var policy = new CacheItemPolicy
    {
        AbsoluteExpiration = absoluteExpiration,
        RemovedCallback = CacheEntryRemovedCallback
    };

    MemoryCache.Default.Add(cacheKey, savedItem, policy);
}

All fairly standard stuff. We also have a method to retrieve cached objects:

public static T GetFromCache<T>(string cacheKey) where T : class
{
    return MemoryCache.Default[cacheKey] as T;
}

I found that if I save an object to the cache as an object of type X and then try and retrieve it from the cache, mistakenly, as an object of type Y, MemoryCache.Default[cachekey] returns null and no exception is thrown. I was expecting something like an InvalidCastException. Can anyone explain why?

immutabl
  • 6,857
  • 13
  • 45
  • 76
  • 3
    You're using the "as" keyword. "as" will either convert the type, or if it's incompatible it'll return a null. If you want an exception then use a cast "(T)" and it'll error. –  Feb 10 '16 at 17:32
  • 2
    See: http://stackoverflow.com/questions/132445/direct-casting-vs-as-operator –  Feb 10 '16 at 17:33
  • 1
    [documentation](https://msdn.microsoft.com/en-us/library/cscsdfbt.aspx) for `as` – juharr Feb 10 '16 at 17:34
  • Thanks for the links, very illuminating. And of course now I'm struggling to understand why anyone would ever use anything other than an explicit cast. – immutabl Feb 11 '16 at 00:13

1 Answers1

2

When you use as it sets the object to null when the cast fails, this is why you also had to add the where T : class to be able to use as because you can't use as on a struct. To get a InvalidCastException you must do a direct cast.

public static T GetFromCache<T>(string cacheKey) //The "where T : class" is no longer needed
{
    return (T)MemoryCache.Default[cacheKey];
}
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • Ah. * sound of penny dropping *. Thanks, this something I didn't look at carefully when I switched from java to c#. Follow-up question: in this scenario, where the code is being accessed as part of a library, do you think it better practice to use a direct cast as opposed to `as`? In my particular case it took an uncomfortably long time to see my mistake - an exception message would have been helpful. – immutabl Feb 11 '16 at 00:10
  • It depends on the library. Whatever you do, just make sure to specify it in the documentation. – Scott Chamberlain Feb 11 '16 at 06:08