38 votes

C # compare deux objets de types inconnus (y compris les types référence et valeur)

Est-il possible en C # de comparer deux objets de types inconnus (y compris les types référence et valeur) à l'aide de leurs comparateurs de types s'ils existent?

Le but est d’écrire une fonction qui aurait une signature comme celle-ci:

 public bool Compare(object a, object b)
{
     // compare logic goes here
}
 

Qui reviendrait

 Compare(100d, 100d) == true
Compare(100f, 100f) == true
Compare("hello", "hello") == true
Compare(null, null) == true 
Compare(100d, 101d) == false
Compare(100f, null) == false

// Use type comparators where possible, i.e.:
Compare(new DateTime(2010, 12, 01), new DateTime(2010, 12, 01)) == true
Compare(new DateTime(2010, 12, 01), new DateTime(2010, 12, 02)) == false
Compare(new DateTime(2010, 12, 01), null) == false
 

Existe-t-il une approche générique pour résoudre ce problème qui conviendrait pour tout type d’objet?

63voto

Jon Skeet Points 692016

Vous pouvez utiliser la statique object.Equals(object x, object y) méthode et pas la peine de la rédaction de votre méthode à tous. Qui va gérer les valeurs null de façon appropriée, et de déléguer à une mise en œuvre de l' object.Equals(object) associée à des x ou y... il ne faut pas question qui, comme Equals est destiné à être symétrique.

Notez que ce n'est pas l'utilisation de l' == opérateurs pour n'importe quel type d'opérateurs ne peuvent pas être remplacés, seulement surchargé (ce qui signifie qu'ils sont choisis au moment de la compilation, pas de temps d'exécution. Dans la plupart des cas Equals devrait faire ce que vous voulez. Dans certains cas, == ne peut pas être surchargé, même si Equals est remplacé... mais je n'ai jamais connu l'inverse soit vrai dans tous les types avec qui j'ai travaillé.

Notez que l'utilisation de cette approche de la boîte de tout types de valeur...

EDIT: Supprimé la section efficacement la réimplanter - mal - EqualityComparer<T>.Default. Voir la réponse de Marc pour en savoir plus. Ce ne sera pas vous aider si vous ne pouvez pas utiliser un type générique, bien sûr.

Un dernier point: je ne voudrais pas appeler votre méthode Compare. Ce nom est généralement associé à la commande de valeurs plutôt que de comparer entre eux pour l'égalité.

20voto

Marc Gravell Points 482669

Une option raisonnable est de travailler avec les génériques, c'est à dire

public bool Compare<T>(T a, T b) {...}

Vous n'aurez pas besoin de spécifier l' T dans votre code, comme le compilateur sera généralement en mesure de le comprendre (c'est à dire vos échantillons existants serait de travailler "en")

Pour la mise en œuvre:

bool equal = EqualityComparer<T>.Default.Equals(x, y);

(pour le type générique, T)

mais en fait je voudrais éviter le mot Compare, qui est utilisé ailleurs pour signifier < / == / > - donc je pourrais avoir:

public static bool Equals<T>(T a, T b) {
    return EqualityComparer<T>.Default.Equals(a, b);
}

Ce:

  • évite de boxe, lorsque T est une struct
  • poignées de valeurs null / Nullable<T> correctement
  • soutient IEquatable<T>
  • ou tombe normal Equals

il ne pas utiliser l' == de l'opérateur, mais MiscUtil a un Operator classe qui va, via

bool equal = Operator.Equal<T>(x,y);

(notez que ce dernier échouera si T n'ont pas de == de l'opérateur, bien que d'y penser, il pourrait utiliser EqualityComparer<T>.Default.Equals comme un secours; il n'a tout simplement pas)


Pour être complet, notons que Comparer<T>.Default.Compare(x,y) gère les opérations de comparaison.

5voto

BlueVoodoo Points 1467

Qu'en est-il de object.equals(x, y) ? Cela acceptera aussi les valeurs nulles.

0voto

Zeemee Points 2519

Qu'en est-il de

 if (a == null && b == null) return true;
if (a == null && b != null) return false;
return (a.equals(b));
 

?

-3voto

KBoek Points 2150

Je ne suis pas sûr à 100% si cela fonctionne dans tous les cas, mais essayez-le

public bool Compare (objet a, objet b)
{
    renvoyer a.Equals (b);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X