阿罗哈,
这是一个覆盖 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);
}