CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features.
There is currently an issue with the GetOrAdd API. In some scenarios, the generic overloads are ambiguous and lead to very odd error behavior which is not easy to spot.
See #152 for more details
Example:
The following code actually compiles because ICacheManager<object> is used
_cache = CacheFactory.Build(c => c.WithDictionaryHandle());
var a = _cache.GetOrAdd("key", (k) => new CacheItem<int>(k, 1));
The factory method of GetOrAdd returns CacheItem<int> and not CacheItem<object> which is a user error.
CacheItem<int> is be treated as object value because it doesn't match T = object and the TCacheValue GetOrAdd(string key, Func<string, TCacheValue> valueFactory) overload will be used.
Now, the GetOrAdd call would cache the CacheItem<int> instead of just the value 1.
And it is not very obvious why this is.
Options to prevent this behavior:
Remove the GetOrAdd overloads with factories taking CacheItem<T>. There are still TryGetOrAdd overloads which are more explicit and have the same functionality
Rename those overloads to GetOrAddCacheItem
Both would be breaking changes although I don't think it would have a very big impact and should be fine.
There is currently an issue with the
GetOrAdd
API. In some scenarios, the generic overloads are ambiguous and lead to very odd error behavior which is not easy to spot.See #152 for more details
Example: The following code actually compiles because
ICacheManager<object>
is usedThe factory method of
GetOrAdd
returnsCacheItem<int>
and notCacheItem<object>
which is a user error.CacheItem<int>
is be treated asobject
value because it doesn't matchT
=object
and theTCacheValue GetOrAdd(string key, Func<string, TCacheValue> valueFactory)
overload will be used.Now, the
GetOrAdd
call would cache theCacheItem<int>
instead of just the value1
. And it is not very obvious why this is.Options to prevent this behavior:
GetOrAdd
overloads with factories takingCacheItem<T>
. There are stillTryGetOrAdd
overloads which are more explicit and have the same functionalityGetOrAddCacheItem
Both would be breaking changes although I don't think it would have a very big impact and should be fine.