私は次のSortedDictionary
ように宣言しました:
SortedDictionary<MyObject,IMyInterface> dict = new SortedDictionary<MyObject,IMyInterface>();
値が入力されたときに、辞書からキーを取得してすぐに参照しようとすると、次のようになりますKeyNotFoundException
。
MyObject myObj = dict.Keys.First();
var value = dict[myObj]; // This line throws a KeyNotFoundException
デバッガーで (エラーの後) 辞書にカーソルを合わせると、参照しようとしたのと同じキーが実際に辞書に含まれていることがはっきりとわかります。ReadOnlyCollection
ofを使用して辞書にデータを入力していMyObjects
ます。そこで何かおかしなことが起きているのではないでしょうか?==
演算子とメソッドをオーバーライドしてEquals
、必要な明示的な比較を取得しようとしましたが、そのような運はありませんでした。実際には から直接キーを取得し、同じキーを使用してDictionary
クエリを実行しているので、それは問題ではありません。Dictionary
何が原因なのかわかりません。誰もこの行動を見たことがありますか?
編集1
オーバーライドEquals
では、(MS が推奨するように) オーバーロードも行いGetHashCode
ました。MyObject
興味のある人のための実装は次のとおりです。
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);
}
}
デバッグから気付いたのKeyNotFoundException
は、式のクイック ウォッチを (がスローされた後に)追加すると、次のようになることです。
dict.ElementAt(0).Key == value;
true を返します。どうすればいいの?
EDIT 2
したがって、問題はSortedDictionary
(およびDictionary
同様に)スレッドセーフではないためです。ディクショナリに対していくつかの操作を実行しているバックグラウンド スレッドがあり、それがコレクションの再利用を引き起こしているようです (コレクションに項目を追加すると、これが実行されます)。同時に、ディクショナリが値を反復処理してキーを見つけたときに、コレクションが変更されていて、そこにあるのにキーを見つけられませんでした。
このコードを求めてくれた皆さん、申し訳ありません。現在、継承したアプリケーションをデバッグしていますが、これが時限のバックグラウンド スレッドで行われていることに気づきませんでした。そのため、関連するすべてのコードをコピーして貼り付けたと思っていましたが、コレクションを操作するすべての背後で別のスレッドが実行されていることに気付きませんでした。