基本上,我已迄今以下:我應該如何去實現Object.GetHashCode()以實現複雜的相等性?
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
。這是一個壞主意,如果是這樣,我該怎麼做呢?
更重要的是,您的散列算法與您的相等算法一致,而不是分佈均勻。請記住,散列的目的僅僅是爲了在散列表中獲得一個體面的分佈;只要你沒有大規模傾向於一個特定的桶,賠率是好的,你會好起來的。如果你擔心,選擇一個合理的情景,你的對象的消費者可能會遇到 - 比方說,將其中的幾百個放在字典中,如果這是合理的 - 並進行一些性能測試,看看你是否可以接受結果。 – 2009-07-02 02:15:42
我在實際使用中見過的最多是〜200,但通常使用<30,所以你可能是對的。 – 2009-07-02 03:02:13
哎呀,在30項以下的情況下,鏈表中的線性搜索可能是合理的表現。你可以總是返回一個零的哈希碼,有100%的碰撞機會,並且仍然可以得到可接受的性能。散列碼分配良好的一點是,當字典大小變大時,可以提高性能。如果只打算在表格中放入少量項目,則可能會出現糟糕的分佈情況,並且仍然會取得良好效果。 – 2009-07-02 18:20:21