Composite key in the dictionary; override GetHashCode (), Equals, etc. or use structures?

I have quite a few dictionaries, where the key is a collection of several different values ​​(mainly strings and integers). I implement these keys as classes (and override GetHashCode() , Equals() , etc.) Or do I use struct instead?

ReSharper makes overriding easier, but the code looks awful. Are there any consequences of using a structure instead?

+4
source share
3 answers

If your only problem is to define equality for use in Dictionary<TKey,TValue> , then the other way you can choose to implement IEqualityComparer<T> . You can manually pass this to the dictionary constructor and take care of comparing the equality for the TKey value without changing the key type.

If you have a more general problem of defining equality for your composite values, I would focus on having the composite value initially support equality. Yes, defining the full set of methods needed for equality is a pain, but basically it is a code plate. The right decision is more important than the useless boiler plate code.

+3
source

I would say that for any structure you always need to manually code the overrides of Equals() and GetHashCode() together with the implementation of IEquatable<T> , if at all possible, that it can be used by someone as a key, so I, of course, I will not use it not to do this.

As with boxing, the default implementation is rather slow, as it uses reflection to examine fields. In addition, there is an error, at least in some versions of the framework (the implementation is reasonably optimized as a binary comparison when it gives the correct results, but, unfortunately, incorrectly evaluates when this is the case, and therefore two structures containing equivalent decimal fields can be considered unequal).

If you need a fast composition that does not make any difference to the system, except for a composite key, I would recommend using Tuple . Tuple.Create() makes it easy to compile, and the overrides for Equals() and GetHashCode() pretty reasonable.

In some cases, it can also be useful to use anonymous classes as keys (only in the context of this method), and here the overrides for Equals() and GetHashCode() also quite reasonable.

+1
source

To create such a composite class, the recommended method is inheritance from Tuple<int, string, ...> .

Thus, you do not need to override GetHashCode and Equals yourself, the base class does this for you.

You can easily provide meaningful access attributes for each field.

 public class CompositeKey : Tuple<string, int> { public CompositeKey(string name, int age) : base(name, age) { } public string Name { get { return Item1; } } public int Age { get { return Item2; } } } 

It also provides immutability, which is suitable for dictionary keys.

In terms of performance, the built-in Tuples are pretty fast. I found that custom structures can be faster, although if you really need every additional bit of performance, it is best to simply encode your key data in int or long.

0
source

Source: https://habr.com/ru/post/1304167/


All Articles