In che modo IEqualityComparerT.Equals e IEqualityComparerT.GetHashCode si comportano in presenza di dati non validi?

0

Nella mia applicazione ho un metodo di servizio che carica alcuni dati. La chiave che identifica i dati è costituita da un tipo di chiave, definito come enum, e da alcuni valori chiave.

public enum KeyType
{
    Alpha,
    Bravo,
    Charlie
}

public class KeyData
{
    public KeyType KeyType { get; set; }
    public string AlphaKey { get; set; }
    public string BravoKey { get; set; }
    public int? CharlieKey { get ;set; }
}

Quali valori chiave sono necessari dipende dal tipo di chiave. Ad esempio per il tipo di chiave Alpha è necessario solo AlphaKey mentre per il tipo di chiave Charlie sono necessari sia BravoKey che CharlieKey . Quando si utilizza la chiave per il caricamento, i valori sconosciuti per il tipo di chiave e / oi valori chiave superflui vengono semplicemente ignorati e non viene restituito alcun dato.

Ora voglio memorizzare le chiavi in una raccolta. Nessuna chiave dovrebbe apparire due volte in questa raccolta. Quando si confrontano le chiavi due devono essere considerate uguali quando hanno lo stesso tipo di chiave e anche tutti i valori chiave necessari per quel tipo sono uguali. Per raggiungere questo obiettivo, voglio creare una classe che implementa IEqualityComparer<KeyData> .

Poiché è menzionato su MSDN che sostituisce GetHashCode non dovrei buttarlo L'ho preso per la mia classe e implementato in questo modo:

public class KeyDataComparer : IEqualityComparer<KeyData>
{
    public int GetHashCode(KeyData obj)
    {
        if (obj == null)
            return 0;

        unchecked
        {
            int hash = 17;

            switch (obj.KeyType)
            {
                case KeyType.Alpha:
                    hash = hash * 486187739 + obj.AlphaKey?.GetHashCode() ?? 0;
                    break;
                case KeyType.Bravo:
                    hash = hash * 486187739 + obj.BravoKey?.GetHashCode() ?? 0;
                    break;
                case KeyType.Charlie:
                    hash = hash * 486187739 + obj.BravoKey?.GetHashCode() ?? 0;
                    hash = hash * 486187739 + obj.CharlieKey?.GetHashCode() ?? 0;
                    break;
                default:
                    // use object.GetHashCode() as a fallback
                    hash = obj?.GetHashCode() ?? 0;
                    break;
            }

            return hash;
        }

Il problema ora è come gestire tipi di chiavi non validi in IEqualityComparer<T>.Equals ? L'ho fatto così:

public bool Equals(KeyData x, KeyData y)
{
    if (x == null)
        return y == null;

    if (x.KeyType != y.KeyType)
        return false;

    switch (x.KeyType)
    {
        case KeyType.Alpha:
            return x.AlphaKey == y.AlphaKey;
        case KeyType.Bravo:
            return x.BravoKey == y.BravoKey;
        case KeyType.Charlie:
            return x.BravoKey == y.BravoKey &&
                x.CharlieKey == y.CharlieKey;
        default:
            throw new InvalidOperationException();
    }
}

Ma questo non sembra corretto perché è un comportamento incoerente. C'è un modo significativo per avere Equals e GetHashCode comportarsi in modo coerente?

    
posta Thomas Schremser 07.12.2017 - 13:56
fonte

1 risposta

4

Puoi restituire false o x.ReferenceEquals(y) ed essere coerente con la tua implementazione GetHashCode .

Tieni presente che dereference y senza verificare che sia null. Un primo controllo più sicuro sarebbe

if ((x == null) != (y == null))
    return false;
    
risposta data 07.12.2017 - 16:22
fonte

Leggi altre domande sui tag