5

I have something like the following to be a key for a generic dictionary.

class IMyClass<T> : IEquatable<IMyClass> where T : struct
{
  //etc
}


class MyClass<T> : IMyClass<T> where T : struct
{
    public bool Equals(IRatingKey<T> other)
    {
       //etc
    }
}

From what I understand of EqualityComparer<T>.Default, it should see that I have implemented IEquatable<T> and therefore create an EqualityComparer on the fly.

Dictionary<TKey, TValue> requires an equality implementation to determine whether keys are equal. If comparer is null, this constructor uses the default generic equality comparer, EqualityComparer<T>.Default. If type TKey implements the System.IEquatable<T> generic interface, the default equality comparer uses that implementation.

However from what I see of using the dictionary indexer Dictionary<T>[], it still relies on overriding GetHashcode e.g public override int GetHashCode()

I can see that there are recommendations to override the lot for consistency, but I'm trying to understand it more. Is it because IEquatable should instead be directly on MyClass rather than in IMyClass? But I'd prefer it on the IMyClass so implementers need to be a dictionary key.

I'm experimenting with IEqualityComparer, but from what I understand I don't need it.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
Alex KeySmith
  • 16,657
  • 11
  • 74
  • 152
  • So using the indexer would certainly use `GetHashCode()`, that's how it **generated the original hash code.** The one used to determine what bucket to place it in when it was added. – Mike Perrenoud Feb 14 '14 at 15:25
  • 2
    hey, any reason to vote for close or downvote? I think if someone not sure how dictionary works, SO is great place to ask... – Arsen Mkrtchyan Feb 14 '14 at 15:36
  • True @MichaelPerrenoud, thanks for the feedback. I've observed that it's needs GetHashCode() and it makes sense to need it. But it's not clear in the documentation, so I wanted to make sure. – Alex KeySmith Feb 14 '14 at 15:45

1 Answers1

2

Dictionary always checks GetHashCode first, than goes forward to look into the elements of the bucket

Assume Dictionary as an Array with length L, on new element addition it calculates the appropriate index like

index = item.GetHashCode() % L

and put that element to the end of the appropriate bucket (just a model, in real word it also takes Abs, and re-build an array if necessary)

So in any point it have the following structure

---
 0  -> Item1, Item2
---
 1  -> Item3
---
 2 
---
...
---
L-1-> Item7

On lookup, dictionary calculates index again, and uses Equality to check only bucket elements of calculated index.

Arsen Mkrtchyan
  • 49,896
  • 32
  • 148
  • 184
  • Thanks Arsen, so in the documentation it's explicit about how other parts of the Dictionary work on the 'outside'. But on the inside for storage it still requires GetHashCode()? – Alex KeySmith Feb 14 '14 at 15:46
  • Am I right on saying that I don't need IEqualityComparer? As EqualityComparer.Default sorts it out for me? – Alex KeySmith Feb 14 '14 at 15:50
  • Yep, IEquatable is the key, which I believe Dictionary.Default will use to create an IEqualityComparer on the fly (kinda?) – Alex KeySmith Feb 14 '14 at 15:55
  • 1
    Yes Alex, Dictinary always calls GetHashCode of key, to determine the bucket, after which it uses IEquatable to loop through bucket elements. Documentation just says the second part, I am sure you can find first element somewhere in the documentation too :) – Arsen Mkrtchyan Feb 14 '14 at 15:56
  • Great thanks, good to see I'm not going mad. I wish there was an IDictionaryKey, it would make it easier :-) – Alex KeySmith Feb 14 '14 at 16:11