簡體   English   中英

什么是.NET Dictionary <T,T> 用於散列引用?

[英]What does .NET Dictionary<T,T> use to hash a reference?

所以我想使用引用類型作為.NET Dictionary的鍵...

例:

class MyObj
{
    private int mID;
    public MyObj(int id)
    {
        this.mID = id;
    }
}

// whatever code here
static void Main(string[] args)
{
    Dictionary<MyObj, string> dictionary = new Dictionary<MyObj, string>();
}

我的問題是,如何為自定義對象生成哈希(即不是int,string,bool等)? 我問,因為在我需要再次在Dictionary中查找內容之前,我用作鍵的對象可能會發生變化。 如果哈希是從對象的地址生成的,那么我可能很好......但是如果它是從對象的成員變量的某種組合生成的那么我就麻煩了。

編輯:

我原本應該明確表示我並不關心在這種情況下對象的相等性......我只是在尋找快速查找(我想在沒有更改代碼的情況下進行1-1關聯涉及的課程)。

謝謝

GetHashCode / Equals的默認實現基本上處理身份 你總是會從同一個對象中獲得相同的哈希值,並且它可能與其他對象不同(非常高的概率!)。

換句話說,如果你只想要參考標識,那你就沒事了。 如果你想使用字典將鍵視為 (即使用對象內的數據,而不僅僅是對象引用本身,以確定相等的概念)那么改變任何相等敏感數據是一個壞主意將其添加到詞典后,在鍵中。

object.GetHashCode的MSDN文檔有點過於可怕 - 基本上你不應該將它用於持久性哈希(即在進程調用之間保存),但它對於同一個對象來說是一致的這就是它所需的全部內容。字典的有效哈希。 雖然它不能保證是唯一的,但我認為你不會遇到足夠的集合來引起問題。

使用的哈希是對象上.GetHashcode方法的返回值。 默認情況下,這基本上是表示引用的值。 它不能保證對象是唯一的,事實上很可能不會在很多情況下。 但是,即使您對對象進行了變異,特定引用的值也不會在對象的生命周期內發生變化。 所以對於這個特定的樣本,你會沒事的。

但總的來說,使用不是不可變的對象作為Dictionary的鍵是一個非常糟糕的主意。 很容易陷入一個陷阱,你在一個對象上重寫Equals和GetHashcode,並破壞該類型以前用作Dictionary中的鍵的代碼。

字典將使用在System.Object定義的GetHashCode方法,該方法不會在對象的生命周期內進行更改,無論字段更改等等。因此,在您描述的方案中不會遇到問題。

您可以覆蓋GetHashCode ,如果重寫Equals ,則應該這樣做,以便相等的對象也返回相同的哈希碼。 但是,如果類型是可變的,那么您必須注意,如果您將對象用作字典的鍵,則如果隨后更改它將無法再次找到它。

GetHashCode方法的默認實現不保證不同對象的唯一返回值。 此外,.NET Framework不保證GetHashCode方法的默認實現,並且它返回的值在不同版本的.NET Framework之間是相同的。 因此,此方法的默認實現不得用作散列目的的唯一對象標識符。

http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

  1. 對於從對象派生的CustomObject,哈希代碼將在對象的開頭生成,並且它們將在其實例的整個生命周期內保持相同。 此外,當內部字段/屬性的值將改變時,哈希代碼將永遠不會改變。

  2. Hashtable / Dictionary不會將GetHashCode用作唯一標識符,而是僅將其用作“哈希桶”。 例如,字符串“aaa123”和“aaa456”可以具有作為“aaa”的散列,並且具有相同散列“aaa”的所有對象將被存儲在一個桶中。 無論何時插入/檢索對象,Dictionary都將始終調用GetHashCode並確定存儲桶以進一步對對象進行單獨的地址比較。

  3. 自定義對象作為字典鍵應該被視為,字典只存儲他們的“引用(地址或內存指針)”它不知道它的內容,對象的內容改變但參考永遠不會改變。 這也意味着如果兩個對象彼此完全相同,但它們的內存不同,則哈希表不會將它們視為相同,因為它們的內存指針不同。

  4. 保證身份平等的最佳方法是覆蓋方法“等於”如下......如果您遇到任何問題。

     class MyObj { private int mID; public MyObj(int id) { this.mID = id; } public bool override Equals(Object obj) { MyObj mobj = obj as MyObj; if(mobj==null) return false; return this.mID == mobj.mID; } } 

暫無
暫無

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

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