Puis-je définir mon type explicite comparateur inline?
Donc .NET 3.0/3.5 nous offre avec beaucoup de nouveaux moyens de la requête, trier et manipuler des données, merci à tous neat fonctions fourni avec LINQ. Parfois, j'ai besoin de comparer les types définis par l'utilisateur qui n'ont pas intégré l'opérateur de comparaison. Dans de nombreux cas, la comparaison est vraiment simple -- quelque chose comme toto1.clé ?= foo2.clé. Plutôt que de créer un nouveau IEqualityComparer pour le type, puis-je simplement indiquer la comparaison inline à l'aide de délégués anonymes/lambda fonctions? Quelque chose comme:
var f1 = ...,
f2 = ...;
var f3 = f1.Except(
f2, new IEqualityComparer(
(Foo a, Foo b) => a.key.CompareTo(b.key)
) );
Je suis sûr que le ci-dessus ne fonctionne pas réellement. Je ne veux pas avoir à faire quelque chose d'aussi "lourd" que l'ensemble de la classe juste pour dire que le programme de façon à comparer des pommes avec des pommes.
- Pour tous ceux à la recherche de la réponse à la question de savoir si la langue prend en charge ce, la réponse est non. Il nécessite quelques petits malins de classes personnalisées.
- Bizarrement, ils ajouté
Comparer<T>.Create
pour créer un Comparateur<T>, mais pas deEqualityComparer<T>.Create()
ce dont nous avons besoin ici. Attention aussi à certaines des remarques ici que de discuter de l'opportunité de mettre en œuvre l'interface ou dériver une nouvelle classe de EqualityComparer : docs.microsoft.com/en-us/dotnet/api/...
Vous devez vous connecter pour publier un commentaire.
Mon MiscUtil bibliothèque contient un ProjectionComparer de construire un IComparer<T> à partir d'une projection de son délégué. Il serait le travail de 10 minutes pour faire un ProjectionEqualityComparer de faire la même chose.
EDIT: Voici le code pour ProjectionEqualityComparer:
Et voici un exemple d'utilisation:
Comparer<T>.Create(...)
mais aucuneEqualityComparer<T>.Create(...)
(qui est essentiellement ce que votre code est).We recommend that you derive from the EqualityComparer<T> class instead of implementing the IEqualityComparer<T> interface, because the EqualityComparer<T> class tests for equality using the IEquatable<T>.Equals method instead of the Object.Equals method. This is consistent with the Contains, IndexOf, LastIndexOf, and Remove methods of the Dictionary<TKey,TValue> class and other generic collections.
, mais qui ne devrait prendre un autre 10 minutes 🙂EqualityComparer.Default
de toute façon. Pouvez-vous un exemple concret où ce code n'est pas, mais elle n'y parviendra que s'il dérivée deEqualityComparer<T>
?ici est une simple classe helper qui devrait faire ce que vous voulez
vous pouvez l'utiliser comme ceci:
GetHashCode
est important. Il n'y a aucun moyen de faire une bonne mise en œuvre avec lacmp
fonction de cette réponse utilise. Cette réponse et le commentaire ci-dessus sont tous les deux en danger. @jonskeets réponse est beaucoup mieux.Je trouve supplémentaire de fournir des aides à IEnumerable est une manière plus propre de le faire.
Voir: cette question
De sorte que vous pourriez avoir:
Si vous définissez les méthodes d'extension correctement
Ce projet a fait quelque chose de similaire: AnonymousComparer - lambda comparer sélecteur de Linq, il a des Extensions pour les Opérateurs de Requête Standard LINQ ainsi.
Pourquoi pas quelque chose comme:
et puis vous pouvez faire par exemple quelque chose comme (par exemple, dans le cas de
Intersect
dansIEnumerable<T>
):La
Comparer
classe peut être mis dans une utilitaires projet et utilisée partout où cela est nécessaire.Je ne vois maintenant le Sam Safran de la réponse (qui est très similaire à celui-ci).
Pour les petits ensembles, vous pouvez le faire:
Pour les grands ensembles, vous voulez quelque chose de plus efficace dans la recherche comme:
Mais, ici, le
Type
de clé doit mettre en œuvreIEqualityComparer
(ci-dessus j'ai supposé que c'était unstring
). Donc, ce n'est pas vraiment répondre à votre question sur l'utilisation d'un lambda dans cette situation, mais il n'en utiliser moins de code que certaines des réponses qui ne.Vous pouvez compter sur l'optimiseur et de raccourcir la deuxième solution:
mais, je n'ai pas d'effectuer des tests pour savoir si elle tourne à la même vitesse. Et que l'un revêtement peut-être trop intelligent pour maintenir.
Construire sur d'autres réponses à la création d'un générique comparer a celle que j'ai le plus aimé. Mais j'ai eu un problème avec Linq
Enumerable.Union
(msdn .Nette de référence) qui était qui son à l'aide de la GetHashCode directement sans prendre en compte est Égale à la remplacer.Qui m'a pris de mettre en œuvre les Comparer comme:
De l'utiliser comme ceci:
Noter que la comparaison de ce que pourrait donner quelques faux positifs étant donné que l'information objet de la comparaison est mappé à un
int
valeur.Comme les autres réponses, mais plus concis c# 7:
alors: