W jaki sposób c # oblicza kod skrótu dla obiektu?

To pytanie wynika z dyskusji na tematkrotki.

Zacząłem myśleć o kodzie skrótu, który powinna mieć krotka. Co jeśli zaakceptujemy klasę KeyValuePair jako krotkę? Nie zastępuje metody GetHashCode (), więc prawdopodobnie nie będzie świadomy kodów mieszających jej „dzieci” ... Tak więc, czas wykonania wywoła Object.GetHashCode (), który nie jest świadomy prawdziwa struktura obiektu.

Następnie możemy utworzyć dwie instancje pewnego typu odniesienia, które są w rzeczywistości Równe, z powodu przeciążenia GetHashCode () i Equals (). I używaj ich jako „dzieci” w krotkach, aby „oszukiwać” słownik.

Ale to nie działa! Czas wykonywania w jakiś sposób określa strukturę naszej krotki i wywołuje przeciążony kod GetHashCode naszej klasy!

Jak to działa? Jaka jest analiza przeprowadzona przez Object.GetHashCode ()?

Czy może wpływać na wydajność w złym scenariuszu, kiedy używamy skomplikowanych kluczy? (prawdopodobnie niemożliwy scenariusz ... ale nadal)

Rozważ ten kod jako przykład:

namespace csharp_tricks
{
    class Program
    {
        class MyClass
        {
            int keyValue;
            int someInfo;

            public MyClass(int key, int info)
            {
                keyValue = key;
                someInfo = info;
            }

            public override bool Equals(object obj)
            {
                MyClass other = obj as MyClass;
                if (other == null) return false;

                return keyValue.Equals(other.keyValue);
            }

            public override int GetHashCode()
            {
                return keyValue.GetHashCode();
            }
        }

        static void Main(string[] args)
        {
            Dictionary<object, object> dict = new Dictionary<object, object>();

            dict.Add(new KeyValuePair<MyClass,object>(new MyClass(1, 1), 1), 1);

            //here we get the exception -- an item with the same key was already added
            //but how did it figure out the hash code?
            dict.Add(new KeyValuePair<MyClass,object>(new MyClass(1, 2), 1), 1); 

            return;
        }
    }
}

Aktualizacja&nbsp;Myślę, że znalazłem wyjaśnienie tego, jak podano poniżej w mojej odpowiedzi. Najważniejsze rezultaty to:

Uważaj na klucze i kody skrótu :-)W przypadku skomplikowanych kluczy słownikowych należy poprawnie zastąpić Equals () i GetHashCode ().