簡體   English   中英

我可以實現一個適用於我的抽象基類的所有擴展的基本GetHashCode()嗎?

[英]Can I implement a base GetHashCode() that will work for all extensions of my abstract base class?

我在這里閱讀了這個問題,這使我在這里讀到了這篇文章

我有一個抽象基類,它允許我約束方法以僅接受擴展我的抽象基類的類(基本多態性)。 我的問題是:我可以在抽象基類中實現GetHashCode()來為任何具體實現提供適當的覆蓋嗎? (即避免在每個具體類中重寫GetHashCode() 。)

我正在想象一個抽象基類中的方法,如下所示:

public abstract class FooBase
{
    private static readonly int prime_seed = 13;
    private static readonly int prime_factor = 7;

    public override int GetHashCode()
    {
        // Seed using the hashcode for this concrete class' Type so
        // two classes with the same properties return different hashes.
        int hash = prime_seed * this.GetType().GetHashCode();
        // Get this concrete class' public properties.
        var props = this.GetType().GetProperties(BindingFlags.Public);
        foreach (var prop in props)
        {
            // Factor in each of this concrete class' public properties' hashcodes.
            hash = (hash * prime_factor) + prop.GetHashCode();
        }
        return hash;
    }
}

這似乎在某些基本的相等單元測試中有效,但是我覺得我已經忽略了一些東西。 我仍然必須在每個具體的類中提供一個重寫,以避免編譯器關於不重寫GetHashCode()的警告,但至少通過這種方式,我不必手動為每個實現編寫一個實現。

它的性能是否優於:

public override int GetHashCode()
{
    return 1;
}

哈希函數的關鍵是它必須快速計算。 通過反射,您可能會失去從哈希獲得的所有好處。

進行基准測試是值得的。

另外,當Equals返回true時,哈希碼必須相等,因此所有子類在其Equals方法中僅使用公共屬性嗎? 如果沒有,您可以考慮遍歷所有屬性,而不僅僅是公共屬性。

編輯以添加:另外,請考慮在屬性循環周圍添加未選中的選項 ,以防止在哈希值大於Int.MaxValue時發生異常。

您錯過了一條基本規則-GetHashCode()結果在對象的整個生存期內必須保持不變。 在您的GetHashCode實現中,不能保證(因為要迭代的屬性是可變的)。

使用反射相當慢,但是在某些情況下可以接受。 當類的實例是哈希表或字典中的鍵時,將使用GetHashCode函數。 在大多數情況下,您知道何時需要它。 有一些工具,例如Resharper示例 ),可以為您生成GetHashCode和Equals函數,而無需手動編寫它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM