Sostituzione di C # equivale a utilizzare & # 8220; come & # 8221; e metodo specializzato per correttezza, flessibilità e prestazioni

StackOverflow https://stackoverflow.com/questions/460846

Domanda

Mi chiedevo quale fosse il modo migliore per implementare un Equals corretto, flessibile e veloce in C #, che può essere usato praticamente per qualsiasi classe e situazione . Ho pensato che un Equals specializzato (prendendo come oggetto un oggetto della classe reale) fosse necessario per le prestazioni. Per evitare la duplicazione del codice, i Pari generali dovrebbero chiamare i Pari specializzati. I controlli null devono essere eseguiti una sola volta, anche nelle classi ereditate.

Alla fine ho pensato a questo design:


class MyClass
{
    public Int32 SomeValue1 = 1;
    public Int32 SomeValue2 = 25;

    // Ignoring GetHashCode for simplicity.

    public override bool Equals(object obj)
    {
        return Equals (obj as MyClass);
    }

    public bool Equals(MyClass obj)
    {
        if (obj == null) {
            return false;
        }

        if (!SomeValue1.Equals (obj.SomeValue1)) {
            return false;
        }

        if (!SomeValue2.Equals (obj.SomeValue2)) {
            return false;
        }

        return true;
    }
}

class MyDerivedClass : MyClass
{
    public Int32 YetAnotherValue = 2;

    public override bool Equals(object obj)
    {
        return Equals (obj as MyDerivedClass);
    }

    public bool Equals(MyDerivedClass obj)
    {
        if (!base.Equals (obj)) {
            return false;
        }

        if (!YetAnotherValue.Equals (obj.YetAnotherValue)) {
            return false;
        }

        return true;
    }
}

Idee importanti:

  • Utilizzo di " as " operatore. In questo modo non è necessario verificare la presenza di null in termini di uguali. I tipi di classe errati vengono ridotti a null e verranno ordinati in Equals specializzato.
  • Controllo null in un preciso punto, anche per le classi derivate.
  • Il controllo degli attributi uno dopo l'altro fornisce una struttura chiara.

Ci sono difetti in questi concetti o ho perso qualche condizione?

È stato utile?

Soluzione

Il tuo metodo Equals non è riflessivo quando sono coinvolti diversi tipi:

MyDerivedClass mdc = new MyDerivedClass();
MyClass mc = new MyClass();
Object omdc = mdc;
Object omc = mc;

// mc.Equals(mdc) - true
// mdc.Equals(mc) - true by calling the right overload
// omc.Equals(omdc) - true
// omdc.Equals(omc) - false, the "as" in MyDerivedClass will result in null

Il modo normale per aggirare questo è usare:

if (GetType() != other.GetType())
{
    return false;
}

Consulta i documenti in Object.Equals : " x. Equals (y) restituisce lo stesso valore di y.Equals (x). & Quot; Fare affidamento sul sovraccarico per fornire risultati diversi potrebbe finire con orribilmente problemi che sarebbero molto sottili da debug.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top