Quelle est la "meilleure" implémentation canonique de Equals () pour les types de référence?

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

  •  09-06-2019
  •  | 
  •  

Question

Implémenter Equals () pour les types de référence est plus difficile qu'il n'y parait. Mon implémentation canonique actuelle est la suivante:

public bool Equals( MyClass obj )
{
  // If both refer to the same reference they are equal.
  if( ReferenceEquals( obj, this ) )
    return true;

  // If the other object is null they are not equal because in C# this cannot be null.
  if( ReferenceEquals( obj, null ) )
   return false;

   // Compare data to evaluate equality    
   return _data.Equals( obj._data );
}

public override bool Equals( object obj )
{
  // If both refer to the same reference they are equal.
  if( ReferenceEquals( obj, this ) )
    return true;

  // If the other object is null or is of a different types the objects are not equal. 
  if( ReferenceEquals( obj, null ) || obj.GetType() != GetType() )
    return false;

  // Use type-safe equality comparison
  return Equals( (MyClass)obj );
}

public override int GetHashCode()
{
  // Use data's hash code as our hashcode  
  return _data.GetHashCode();
}

Je pense que cela couvre tous les cas de figure (héritage, etc.) mais je me trompe peut-être. Qu'en pensez-vous?

Était-ce utile?

La solution

J'ai écrit un guide assez complet à ce sujet il y a quelque temps. Pour commencer, vos implémentations equals doivent être partagées (c'est-à-dire que la surcharge prenant un objet doit être transmise à celui prenant un objet fortement typé). De plus, vous devez prendre en compte des éléments tels que votre objet doit être immuable en raison de la nécessité de remplacer GetHashCode. Plus d'infos ici:

http://gregbeech.com/blog/implementing-object-equality -en-dotnet

Autres conseils

Mieux espérer que this._data n'est pas nul s'il s'agit également d'un type de référence.

public bool Equals( MyClass obj )
{
    if (obj == null) {
        return false;
    }
    else {
        return (this._data != null && this._data.Equals( obj._data ))
                         || obj._data == null;
    }
}

public override bool Equals( object obj )
{
    if (obj == null || !(obj is MyClass)) {
        return false;
    }
    else {
        return this.Equals( (MyClass)obj );
    }
}

public override int GetHashCode() {
    return this._data == null ? 0 : this._data.GetHashCode();
}

En ce qui concerne l'héritage, je pense que vous devriez simplement laisser le paradigme OO faire sa magie.

Plus précisément, la vérification GetType () doit être supprimée, elle pourrait rompre le polymorphisme sur toute la ligne.

Je suis d'accord avec chakrit, les objets de types différents doivent être autorisés à être sémantiquement égaux s'ils ont les mêmes données ou identifiants.

Personnellement, j'utilise les éléments suivants:

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

        return this.data.Equals(other.data);
    }

Cela dépend si vous écrivez un type de valeur ou un type de référence. Pour un type de valeur triable, je recommande ceci: Un extrait de code pour Visual Studio 2005 qui implémente un type de valeur squelette conforme aux instructions de conception de structure

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top