Sostituzione di C # equivale a utilizzare & # 8220; come & # 8221; e metodo specializzato per correttezza, flessibilità e prestazioni
-
19-08-2019 - |
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?
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.