アロハ、
GetHashCode をオーバーライドする単純なクラスを次に示します。
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
}
そのクラスのインスタンスを作成したら、それを HashSet に追加し、その 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 から何かを削除する方法が間違っていますか?
これを読んでいただきありがとうございます。
更新: 混乱を避けるために、Equals() は次のとおりです。
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);
}