基本上,到目前为止我有以下内容:

class Foo {
    public override bool Equals(object obj)
    {
        Foo d = obj as Foo ;
        if (d == null)
            return false;

        return this.Equals(d);
    }

    #region IEquatable<Foo> Members

    public bool Equals(Foo other)
    {
        if (this.Guid != String.Empty && this.Guid == other.Guid)
            return true;
        else if (this.Guid != String.Empty || other.Guid != String.Empty)
            return false;

        if (this.Title == other.Title &&
            this.PublishDate == other.PublishDate &&
            this.Description == other.Description)
            return true;

        return false;
    }
}

所以,问题是这样的:我有一个非必填字段 Guid, ,这是一个唯一标识符。如果未设置,那么我需要尝试根据不太准确的指标来确定相等性,以尝试确定两个对象是否相等。这工作正常,但它使 GetHashCode() 凌乱的...我该怎么办?一个简单的实现是这样的:

public override int GetHashCode() {
    if (this.Guid != String.Empty)
        return this.Guid.GetHashCode();

    int hash = 37;
    hash = hash * 23 + this.Title.GetHashCode();
    hash = hash * 23 + this.PublishDate.GetHashCode();
    hash = hash * 23 + this.Description.GetHashCode();
    return hash;
}

但这两种类型的哈希发生冲突的可能性有多大?当然,我没想到会是这样 1 in 2 ** 32. 。这是一个坏主意吗?如果是的话,我应该怎么做?

有帮助吗?

解决方案

我不认为这是与您选择使用的方法有问题。令人担忧的“过多”有关哈希冲突几乎总是指示过思考的问题;只要散列极有可能是不同的,你应该罚款。

最后你甚至要考虑从您的哈希离开了Description无论如何,如果它是合理的期望,大部分时间对象都可以根据自己的标题和发布日期尊贵(书吗?)。

您甚至可以考虑在你的哈希函数不顾GUID干脆,只有使用它在Equals实施消除歧义哈希冲突的可能性不大(?)的情况下。

其他提示

一个非常简单的 自定义类的哈希码方法 是将每个字段的哈希码按位异或在一起。它可以像这样简单:

int hash = 0;
hash ^= this.Title.GetHashCode();
hash ^= this.PublishDate.GetHashCode();
hash ^= this.Description.GetHashCode();
return hash;

来自 上面的链接:

XOR 具有以下优良特性:

  • 它不依赖于计算顺序。
  • 它不会“浪费”比特。如果更改其中一个组件中的哪怕一位,最终值都会发生变化。
  • 即使在最原始的计算机上,它也很快,只需一个周期。
  • 它保持均匀分布。如果你组合的两块是均匀分布的,那么组合也会是均匀分布的。换句话说,它不会将摘要的范围压缩成更窄的范围。

如果您希望字段中存在重复值,则异或效果不佳,因为异或时重复值会相互抵消。由于您将三个不相关的字段散列在一起,因此在这种情况下应该不是问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top