I come from a python world where only hashable objects may be used as keys to a dictionary. Is there a similar restriction in C#? Can you use custom types as dictionary keys?
问题:
回答1:
The requirement for a dictionary key is that it is comparable and hashable. That's turtles all the way down in .NET, every type (other than pointer types) derives from System.Object and it is always comparable thanks to its Equals() method. And hashable thanks to its GetHashCode() method. So any .NET type automatically can be used as a key.
If you want to use your own type as the key then you only need to do something special if you want to re-define object identity. In other words, if you need the ability for two distinct objects to be equal. You'd then override the Equals() method, typically comparing fields of the object. And then you must also override GetHashCode(), equal objects must generate the same hash code.
If the type cannot be changed or you want to customize the behavior especially for the Dictionary then you can pass a custom IEqualityComparer<> to the constructor. Keep in mind that the quality of the hash code you generate with your own GetHashCode() determines the dictionary efficiency.
回答2:
Yes you can, just implement interface IEqualityComparer, override GetHashCode and Equals.
回答3:
Yes, the important thing with keys is that they implement (or have a good default implementation of) GetHashCode
and Equals
. The Dictionary<T, K>
implementation can take advantage of generic IEqualityComparer<T>
.
All custom types will come with a default implementation of GetHashCode
and Equals
because these are members of object
, however, that default might not always be relevant to your type.
The dictionary first attempts to get the hash code to determine the bucket the value will land in. If there is a hash collision, it falls back onto equality (I think).
Do note that the type of key you use (class
, struct
, primitive type, etc) can yield different performance characteristics. In our code base we found that the default implementation of GetHashCode
in struct
wasn't as fast as overriding it ourselves. We also found that nested dictionaries perform better in terms of access time than a single dictionary with a compound key.