Je veux que ma Food
classe puisse tester chaque fois qu'elle est égale à une autre instance de Food
. Je l'utiliserai plus tard contre une liste, et je veux utiliser sa List.Contains()
méthode. Dois-je mettre en œuvre IEquatable<Food>
ou simplement remplacer Object.Equals()
? Depuis MSDN:
Cette méthode détermine l'égalité à l'aide du comparateur d'égalité par défaut, tel que défini par l'implémentation de l'objet de la méthode IEquatable.Equals pour T (le type de valeurs dans la liste).
Ma prochaine question est donc la suivante: quelles fonctions / classes du framework .NET utilisent Object.Equals()
? Dois-je l'utiliser en premier lieu?
Réponses:
La principale raison est la performance. Lorsque les médicaments génériques ont été introduits dans .NET 2.0 , ils ont été en mesure d'ajouter un tas de classes soignées telles que
List<T>
,Dictionary<K,V>
,HashSet<T>
, etc. Ces structures font un usage intensif deGetHashCode
etEquals
. Mais pour les types de valeur, cela nécessitait de la boxe.IEquatable<T>
permet à une structure d'implémenter uneEquals
méthode fortement typée donc aucune boxe n'est requise. Ainsi, de bien meilleures performances lors de l'utilisation de types valeur avec des collections génériques.Les types de référence ne bénéficient pas autant, mais l'
IEquatable<T>
implémentation vous permet d'éviter un castSystem.Object
dont peut faire la différence s'il est appelé fréquemment.Comme indiqué sur le blog de Jared Parson , vous devez toujours implémenter les remplacements d'objets.
la source
IEquatable<T>
interface fait-elle autre chose que rappeler à un développeur d'inclure unpublic bool Equals(T other)
membre dans la classe ou la structure? La présence ou l'absence de l'interface ne fait aucune différence au moment de l'exécution. La surcharge deEquals
semble être tout ce qui est nécessaire.Selon le MSDN :
Il semble donc qu'il n'y ait pas de réelle différence fonctionnelle entre les deux, sauf que l'un ou l'autre pourrait être appelé en fonction de la façon dont la classe est utilisée. Du point de vue des performances, il est préférable d'utiliser la version générique car aucune pénalité de boxe / déballage n'est associée.
D'un point de vue logique, il est également préférable d'implémenter l'interface. Remplacer l'objet ne dit vraiment à personne que votre classe est en fait égalable. Le remplacement peut simplement être une classe ne rien faire ou une implémentation superficielle. L'utilisation de l'interface dit explicitement, "Hé, cette chose est valable pour la vérification d'égalité!" C'est juste un meilleur design.
la source
Prolonger ce que Josh a dit avec un exemple pratique. +1 à Josh - J'étais sur le point d'écrire la même chose dans ma réponse.
De cette façon, j'ai la méthode Equals () réutilisable qui fonctionne hors de la boîte pour toutes mes classes dérivées.
la source
Si nous appelons
object.Equals
, cela oblige à une boxe coûteuse sur les types de valeur. Cela n'est pas souhaitable dans les scénarios sensibles aux performances. La solution est d'utiliserIEquatable<T>
.L'idée derrière
IEquatable<T>
est que cela donne le même résultat queobject.Equals
mais plus rapidement. La contraintewhere T : IEquatable<T>
doit être utilisée avec des types génériques comme ci-dessous.sinon, il se lie à
slower object.Equals()
.la source