Pourquoi je ne peux pas comparer un KeyValuePair<TKey, TValue> à défaut
Dans .Net de 2,5 je peux habituellement obtenir une comparaison d'égalité (==) entre une valeur et son type par défaut
if (myString == default(string))
Mais j'ai l'exception suivante lorsque j'essaie d'exécuter une comparaison d'égalité sur un défaut KeyValuePair et un KeyValuePair
Exemple de Code (à partir d'une pré-extension de la méthode, de la proto-lambda statique ListUtilities classe 🙂 )
public static TKey
FirstKeyOrDefault<TKey, TValue>(Dictionary<TKey, TValue> lookups,
Predicate<KeyValuePair<TKey, TValue>> predicate)
{
KeyValuePair<TKey, TValue> pair = FirstOrDefault(lookups, predicate);
return pair == default(KeyValuePair<TKey, TValue>) ?
default(TKey) : pair.Key;
}
Exception:
Opérateur '==' ne peut pas être appliquée à
des opérandes de type
'Système.Les Collections.Génériques.KeyValuePair<string,object>'
et
'Système.Les Collections.Génériques.KeyValuePair<string,object>'
Est-ce parce que, comme un struct, le KeyValuePair n'est pas nullable? Si c'est le cas, pourquoi, comme, sans doute, par défaut a été mis en œuvre pour gérer pas les types nullables?
MODIFIER
Pour l'enregistrement, j'ai choisi @Chris Hannon comme réponse sélectionnée, car il m'a donné ce que je cherchais, le plus élégant de l'option, et une brève explication, cependant, je fais de la promotion de la lecture @Dasuraga pour un ensemble très complet qui explique pourquoi c'est le cas
- FirstOrDefault<KeyValuePair<TKey,TValue>>(recherches, prédicat) ?
- Pellerin, qui doit être déduit du type transmis, ou le compilateur qui se serait plaint. L'exception se produit également lorsque vous simplifier à myKvp == défaut(KeyValuePair<...>)
- Sûrement les valeurs par défaut sont dressées à des types scalaires? Que signifie, pour un KVP, pour avoir une valeur par défaut? J'imagine que vous avez une réponse à cette question dans le contexte de ce que vous essayez de construire. Je suppose que pour les non-scalaires la valeur par défaut est ce que vous obtenez à partir de l'appel du néant constructeur. Dans ce cas, je m'attends à l'identité de l'objet de la comparaison de fausse déclaration puisque vous obtenez un nouvel objet à chaque fois que le constructeur est appelé.
Vous devez vous connecter pour publier un commentaire.
Cela se produit parce que
KeyValuePair<TKey, TValue>
ne définit pas une coutume opérateur == et n'est pas inclus dans la liste prédéfinie des types de valeur qui peut l'utiliser.Voici un lien vers le La documentation MSDN pour l'opérateur.
Votre meilleur pari pour un contrôle d'égalité dans ce cas, parce que ce n'est pas une struct vous avez plus de contrôle, c'est d'appeler
default(KeyValuePair<TKey,TValue>).Equals(pair)
à la place.(object)kvp1 == (object)kvp2
effectuer une référence à l'égalité. Le casting est important de modifier le type de compilation pour vous assurer queobject.==(object)
est appelée est un opérateur défini.(Si vous n'avez pas de soins sur les génériques de discussion lié à cette erreur, vous pouvez simplement sauter à la fin de votre "vraie" réponse)
Que l'erreur dit, il n'y a pas d'égalité des tests pour KeyValuePairs (à savoir qu'il n'est pas intégré dans la méthode de comparaison). La raison pour cela est pour éviter d'avoir à placer des contraintes sur les types de KeyValuePairs (il existe de nombreux cas où les clés,les comparaisons de la valeur ne sera jamais rendu).
Évidemment, si vous voulez comparer th KeyValuePairs, j'imagine ce que vous voulez est de vérifier si les clés et les valeurs sont égales. Mais cela implique un gâchis de choses , notamment que TKey et TValue sont les deux types comparables (c'est à dire qu'ils implémentent l'interface IComparable)
Vous pouvez écrire votre propre fonction de comparaison entre keyvaluepairs, par exemple:
(Excusez le terrible indentation)
Ici, nous l'imposer TKey et TValue sont à la fois comparables (via le CompareTo fonction de membre).
La CompareTo fonction (telle que définie pour le pré-types définis par l') renvoie 0 lorsque deux objets sont égaux , à la strcmp . un.ComparesTo(b)==0 signifie que a et b sont de la "même"(en valeur, pas le même objet).
de sorte que cette fonction devrait prendre deux KVPs (k,v) et (k',v') et qui renvoie true si et seulement si k==k' et v==v' (au sens intuitif).
Mais est-ce nécessaire? Il semble que votre test où vous rencontrez des problèmes est basée sur une sorte de vérification sur le retour de FirstOrDefault.
Mais il y a une raison pour laquelle votre fonction est appelée FirstOrDefault:
(l'emphase est mienne)
Cette fonction retourne les valeurs par défaut si quelque chose n'est pas trouvé, de sens que si votre prédicat n'est pas vérifié, vous aurez un KeyValuePair égal à (la valeur par défaut(TKey),par défaut(TValue).
Votre code donc (entend) vérifier si la paire.Key==défaut(TKey), seulement pour de retour par défaut(TKey) de toute façon. Ne serait-il pas juste faire plus de sens de retour de la paire.Clé dès le début?
Pour vous d'utiliser le "==" opérateur d'égalité sur une catégorie ou d'une structure, il doit remplacer l'opérateur: http://msdn.microsoft.com/en-us/library/ms173147(v=vs. 80).aspx
KeyValuePair ne l'est pas, et, par conséquent, vous obtenez l'erreur de compilation. Remarque, vous obtiendrez le même message d'erreur si vous essayez ceci:
EDIT: Comme Eric Lippert corrigé moi dans les commentaires, les classes de toute évidence n'a pas besoin de surcharger l'opérateur d'égalité pour "==" pour être valide. Il va compiler amende et de faire une référence à l'égalité de vérifier. Mon erreur.
Il échoue pour la même raison que les suivantes:
L'indice est dans le message d'erreur, naturellement. (Il n'a rien à voir avec
default
).L'opérateur
==
n'est pas définie pourKeyValuePair<T,U>
.Messages d'erreur FTW.
Heureux de codage.
Les valeurs par défaut sont dressées à des types scalaires.
Posez-vous cette question: est-Ce dire pour KVP, pour avoir une valeur par défaut?
Pour les non-scalaires la valeur par défaut est ce que vous obtenez à partir de l'appel du néant constructeur. En supposant que KVP est Égal effectue exemple l'identité de comparaison, je m'attends à ce qu'il renvoie faux, puisque vous obtenez un nouvel objet à chaque fois que le constructeur est appelé.
new KVP("Hello", "World") == new KVP("Hello", "World")
à compiler. Cependant, pour assurer la==
contrat (a.Key == b.Key && a.Value == b.Value
) il faudrait donc que les arguments génériques a également répondu à==
, qui ne peut pas être appliquée au moment de la compilation. Rappelez-vous, chaque type, des structures personnalisées comprennent, ont une valeur par défaut.Ceci va dans une direction légèrement différente, mais je suis en supposant que vous avez interrogé un Dictionnaire pour obtenir ce résultat, et que vous voulez vérifier si elle a retourné un résultat valide ou pas.
J'ai trouvé la meilleure façon de le faire était d'interroger la valeur réelle au lieu de l'ensemble de la KeyValuePair, comme ceci:
var valitem = MyDict.Des valeurs.FirstOrDefault(x=> x.Quelque chose == aVar);
Vous pouvez maintenant vérifier si valitem est null ou pas. Encore une fois, il ne veut pas répondre directement à votre question, mais il offre ce qui pourrait être une approche alternative à votre objectif.