aspnet/Caching

MemoryCache does not find item when simple object used as a key.

rcollette opened this issue · 3 comments

If I set an item in the cache using a simple object as a key:

class MyCacheKey{
    public string SomeProperty {get;set;}
}

The item will subsequently not be found when trying to get the item.

I tried debugging this and found that when it reaches the method TryGetValueInternal of concurrentDictionary, the first line (at least as decompiled by Rider), is

ConcurrentDictionary<TKey, TValue>.Tables tables = this._tables;

In my debugger/inspector, this._tables is non-null. However, after the line of code is executed, the tables variable is null. Consequently, no item is returned.

There is nothing in the documentation stating that only a string may be used as the cache key so I presume this should work. If not, then it would be helpful if the documentation were updated to reflect what values/types are valid for cache keys.

// Assembly: Microsoft.Extensions.Caching.Memory, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60

Sorry. After a bit more digging, I realized that equality members must be implemented.

I saw a comment about the unit tests which suggested that this scenario should be included in the tests, but it was not. Documentation or at least a test would help clarify for the user.

Actually, I've implemented equality comparers and this is still an issue.

        private class MaxLocationCountCacheKey
        {
            private readonly string _typeName = typeof(MaxLocationCountCacheKey).FullName;

            // ReSharper disable once NotAccessedField.Local
            private readonly string _subscriptionId;

            public MaxLocationCountCacheKey(string subscriptionId)
            {
                _subscriptionId = subscriptionId;
            }

            public MaxLocationCountCacheKey(Subscription subscription)
            {
                _subscriptionId = subscription.SubscriptionId;
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                {
                    return false;
                }

                if (ReferenceEquals(this, obj))
                {
                    return true;
                }

                return obj.GetType() == GetType() && Equals((MaxLocationCountCacheKey) obj);
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    return ((_typeName != null ? _typeName.GetHashCode() : 0) * 397) ^
                           (_subscriptionId != null ? _subscriptionId.GetHashCode() : 0);
                }
            }

User to keyboard error. Keys were not being used consistently.