Sobes.tech
Middle

Co należy zrobić, aby użyć klasy jako klucza w kolekcji?

sobes.tech AI

Odpowiedź od AI

Aby używać klasy jako klucza w kolekcji (np. w Dictionary<TKey, TValue>), konieczne jest poprawne zaimplementowanie metod Equals i GetHashCode.

  1. Nadpisanie Equals(object obj):

    • Porównanie bieżącego obiektu z innym obiektem (obj) w celu sprawdzenia równości.
    • Upewnienie się, że obj nie jest null.
    • Upewnienie się, że obj ma ten sam typ co bieżący obiekt.
    • Porównanie istotnych pól lub właściwości obu obiektów.
  2. Nadpisanie GetHashCode():

    • Wygenerowanie kodu hash na podstawie tych samych istotnych pól lub właściwości, które są używane w Equals.
    • Zapewnienie, że jeśli Equals zwraca true dla dwóch obiektów, to ich GetHashCode zwraca tę samą wartość.
    • Zaleca się równomierne rozłożenie kodów hash, aby zmniejszyć kolizje.
  3. Opcjonalnie implementacja IEquatable<T>:

    • Udostępnia typowaną metodę Equals(T other), która może być bardziej wydajna, unikając boxing dla typów wartości.

Przykład:

using System;
using System.Collections.Generic;

public class MyKey
{
    public int Id { get; }
    public string Name { get; }

    public MyKey(int id, string name)
    {
        Id = id;
        Name = name;
    }

    // Nadpisanie Equals do porównania po wartościach
    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }

        MyKey other = (MyKey)obj;
        return Id == other.Id && Name == other.Name;
    }

    // Nadpisanie GetHashCode z użyciem tych samych pól
    public override int GetHashCode()
    {
        // Użycie Tuple do łączenia hashów
        return (Id, Name).GetHashCode();
    }

    // Opcjonalnie implementacja IEquatable<T>
    public bool Equals(MyKey other)
    {
        if (other == null)
        {
            return false;
        }
        return Id == other.Id && Name == other.Name;
    }
}

Bez poprawnej implementacji tych metod, domyślnie Dictionary będzie używał równości tożsamości (porównanie referencji) i domyślnej implementacji GetHashCode (opartej na referencji), co może prowadzić do nieprawidłowego działania kolekcji podczas wyszukiwania kluczy po wartościach.