J'ai un SortedDictionary
déclaré comme tel:Récupéré Dictionnaire clé non trouvé
SortedDictionary<MyObject,IMyInterface> dict = new SortedDictionary<MyObject,IMyInterface>();
Lorsque son avec les valeurs, si je prends une clé du dictionnaire et essaie ensuite de faire référence immédiatement après, je reçois un KeyNotFoundException
:
MyObject myObj = dict.Keys.First();
var value = dict[myObj]; // This line throws a KeyNotFoundException
Comme je l'ai Survoler la dictionnaire (après l'erreur) avec le débogueur, je peux voir clairement la même clé que j'ai essayé de faire référence est en fait contenue dans le dictionnaire. Je suis en train de remplir le dictionnaire en utilisant un ReadOnlyCollection
de MyObjects
. Peut-être que quelque chose d'étrange se passe là-bas? J'ai essayé de remplacer l'opérateuret les méthodes Equals
pour obtenir la comparaison explicite que je voulais, mais pas une telle chance. Cela ne devrait vraiment pas importer puisque je reçois une clé directement à partir du Dictionary
puis en interrogeant le Dictionary
en utilisant cette même clé. Je ne peux pas comprendre ce qui cause cela. Quelqu'un at-il déjà vu ce comportement?
EDIT 1
Dans primordial Equals
je surchargée aussi (comme MS recommande) GetHashCode
aussi bien. Voici la mise en œuvre de MyObject
pour toute personne intéressée:
public class MyObject
{
public string UserName { get; set;}
public UInt64 UserID { get; set;}
public override bool Equals(object obj)
{
if (obj == null || GetType()!= obj.GetType())
{
return false;
}
// Return true if the fields match:
return this.Equals((MyObject)obj);
}
public bool Equals(MyObject other)
{
// Return true if the fields match
return this.UserID == other.UserID;
}
public override int GetHashCode()
{
return (int)this.UserID;
}
public static bool operator ==(MyObject a, MyObject b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return a.UserID == b.UserID
}
public static bool operator !=(MyObject a, MyObject b)
{
return !(a == b);
}
}
Ce que je remarquai de débogage est que si j'ajoute une montre rapide (après la KeyNotFoundException
est moulinée) pour l'expression:
dict.ElementAt(0).Key == value;
il retourne vrai . Comment se peut-il?
EDIT 2 Le problème a fini par être parce que SortedDictionary
(et Dictionary
ainsi) ne sont pas thread-safe. Il y avait un thread d'arrière-plan qui exécutait certaines opérations sur le dictionnaire qui semblaient déclencher un recours de la collection (l'ajout d'éléments à la collection le ferait). En même temps, quand le dictionnaire itérait à travers les valeurs pour trouver ma clé, la collection était en train d'être changée et elle ne trouvait pas ma clé même si elle était là.
Désolé pour tous ceux qui ont demandé du code sur celui-ci, je suis en train de déboguer une application dont j'ai hérité et je ne me suis pas rendu compte que cela se passait sur un thread de fond temporisé. En tant que tel, je pensais avoir copié et collé tout le code pertinent, mais je n'avais pas réalisé qu'il y avait un autre fil conducteur derrière tout ce qui manipulait la collection.
Vous devez * remplacer * Equals (et GetHashCode), mais vous pouvez également vouloir le surcharger. Veuillez montrer votre classe - ou plutôt, un programme court mais complet démontrant le problème. –
Pour être clair: Vous avez observé ceci en premier sans surcharge/surcharge de Equals/==/GetHashCode? Parce qu'une implémentation défectueuse de ceux-ci serait la réponse facile. –
@JonSkeet - Vous avez raison, j'ai mal tapé. J'ai fait _override_ les méthodes 'Equals' (et' GetHashCode'). J'ai ajouté le code pertinent. –