Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What can you use as keys in a C# dictionary?

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?

like image 221
static_rtti Avatar asked Sep 06 '13 08:09

static_rtti


3 Answers

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.

like image 82
Hans Passant Avatar answered Sep 29 '22 03:09

Hans Passant


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.

like image 38
Adam Houldsworth Avatar answered Sep 29 '22 03:09

Adam Houldsworth


Yes you can, just implement interface IEqualityComparer, override GetHashCode and Equals.

like image 41
Suhan Avatar answered Sep 29 '22 05:09

Suhan