アロハ、HashSetの<T> .RemoveWhere()とGetHashCodeメソッド()
はここGetHashCodeメソッドをオーバーライドする単純なクラスです:私は、そのクラスのインスタンスを作成する場合は、HashSetのに追加
class OverridesGetHashCode
{
public string Text { get; set; }
public override int GetHashCode()
{
return (Text != null ? Text.GetHashCode() : 0);
}
// overriding Equals() doesn't change anything, so I'll leave it out for brevity
}
、その後、このように、Textプロパティを変更します。
var hashset = new HashSet<OverridesGetHashCode>();
var oghc = new OverridesGetHashCode { Text = "1" };
hashset.Add(oghc);
oghc.Text = "2";
を、これは動作しません:
var removedCount = hashset.RemoveWhere(c => ReferenceEquals(c, oghc));
// fails, nothing is removed
Assert.IsTrue(removedCount == 1);
とどちらが行い、この:
// this line works, i.e. it does find a single item matching the predicate
var existing = hashset.Single(c => ReferenceEquals(c, oghc));
// but this fails; nothing is removed again
var removed = hashset.Remove(existing);
Assert.IsTrue(removed);
私はそれが内部的に項目が挿入され、それが本当ならば、それはhashset.Contains(oghc)が動作しないことは理解 だ時に生成された使用ハッシュを推測します。 また、ハッシュコードで項目を検索し、一致するものが見つかった場合にのみ、述語をチェックして、最初のテストが失敗する理由が考えられます(ここでもまた推測しています)。 しかし、なぜ最後のテストが失敗するのですか、私はちょうどハッシュセットからそのオブジェクトを持っていますか?私は何かを見逃していますか、これはHashSetから何かを削除するための間違った方法ですか?
この度は読んでいただきありがとうございます。
UPDATE:そのオブジェクトはHashSet
の契約に違反しているHashSet
に使用されている間、あなたのオブジェクトのハッシュコードを変更することにより
protected bool Equals(OverridesGetHashCode other)
{
return string.Equals(Text, other.Text);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((OverridesGetHashCode) obj);
}
Eric Lippertの[GetHashCodeのガイドラインとルール](http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for- gethashcode.aspx)特に* GetHashCodeによって返されたルールは、安定したままのハッシュコードに依存するデータ構造体にオブジェクトが含まれている間は変更してはいけません。 –
私は最初これが良い質問だったと思ったので、私は何か本当にばかげて尋ねたような気分になりました:)しばらくしてから意味があります。 「私はHashSetを使用したことがありません」と私が思いつくべき最善の言い訳です:Dありがとうございます。 –