Class or Struct for cache key

Viewed 423

So I'm designing a data type to use as the cache key in a memory cache. There will be millions of entries for this cache and I'm wondering which of a class or struct would be most appropriate for this purpose any why. I have read the MS guidelines on this matter and they suggest:

It logically represents a single value, similar to primitive types (int, double, etc.).

I think it does.

It has an instance size under 16 bytes.

No, since the guid alone is 16 bytes

It is immutable.

Yes

It will not have to be boxed frequently.

Yes

As it currently looks:

    internal class ProductKey : IEquatable<ProductKey>
    {
        private Guid MerchantId { get; }
        private string ProductId { get; }

        public ProductKey(Guid merchantId, string productId)
        {
            MerchantId = merchantId;
            ProductId = productId;
        }

        public bool Equals(ProductKey other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return
                string.Equals(ProductId, other.ProductId, StringComparison.OrdinalIgnoreCase) &&
                MerchantId.Equals(other.MerchantId);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((ProductKey)obj);
        }

        public override int GetHashCode()
        {
            var hashCode = new HashCode();
            hashCode.Add(MerchantId);
            hashCode.Add(ProductId, StringComparer.OrdinalIgnoreCase);
            return hashCode.ToHashCode();
        }
    }
1 Answers

Struct usage greatly depends on the whole environment which they will be used. It is not just simply that uses less memory, it has a change in semantics that is non trivial too.

Structs are marshalled by value, that is, they are copied. Classes are marshalled by reference.

C# 7 and 8 introduce many optimizations for structures, nonetheless, if used incorrectly, they could cause more harm than good.

There already is a long-standing debate about this hot topic. You may want to take a look at this SO question: you'll see that there are many different scenarios, with different ideas.

Just a note for your particular case, your structure holds a reference, therefore you'll save memory when your structure is copied because you only have one integer and a pointer to marshal, but you won't gain any performance in accessing the string, as it is allocated elsewhere. This means that code locality won't improve.

Related