1

我想使用ConcurrentDictionary來檢查此數據密鑰是否已經添加過,但看起來我仍然可以添加之前添加的密鑰。ConcurrentDictionary不止一次添加相同的密鑰

代碼:

public class pKeys 
    { 
     public pKeys() 
     { } 
     public pKeys(long sID, long pID) 
     { 
      this.seID = sID; 
      this.pgID = pID; 

     } 
     public long seID; 
     public long pgID; 
    } 

    public static ConcurrentDictionary<pKeys, bool> existenceDic 
= new ConcurrentDictionary<pKeys, bool>(); 

測試代碼:

pKeys temKey = new pKeys(111, 222); 
    bool res = existenceDic.TryAdd(temKey, true); 
    Console.WriteLine(res); 

    temKey = new pKeys(111, 222); 
    res = existenceDic.TryAdd(temKey, true); 
    Console.WriteLine(res); 

結果:

true 
true 
+1

您的'pKeys'對象不會覆蓋'GetHashCode()'或'Equals()',所以這兩個不同的實例被認爲是不同的值。要麼使用同一個實例兩次(而不是第二次調用'new'),要麼正確地覆蓋這些方法,以便包含相同值的不同實例被認爲是相同的值。 –

+0

也許很容易修復,我只是將兩個元素鍵轉換成一個字符串,然後像散列一樣工作.... –

+0

不,不要這樣做。如果這樣做,那麼(11,1222)的值將具有與(111,222)的值相同的哈希碼,因爲沒有很好的理由。衝突不是致命的,但是您應該設計哈希碼實現,至少儘量避免它們。 –

回答

2

您可以添加含有相同的值兩個不同的實例,因爲你還沒有覆蓋GetHashCode()Equals()。這會導致使用默認的相等比較,參考類型只是比較引用本身。在這種情況下,兩個不同的實例始終被視爲不同的值。

一個選項是讓您的類型爲struct而不是class。這使用一個默認的比較來考慮字段值。

或者,您可以繼續並覆蓋GetHashCode()Equals()。例如:

public class pKeys 
{ 
    public pKeys() 
    { } 
    public pKeys(long sID, long pID) 
    { 
     this.seID = sID; 
     this.pgID = pID; 

    } 
    public readonly long seID; 
    public readonly long pgID; 

    public override int GetHashCode() 
    { 
     return seID.GetHashCode() * 37 + pgID.GetHashCode(); 
    } 

    public override bool Equals(object other) 
    { 
     pKeys otherKeys = other as pKeys; 

     return otherKeys != null && 
      this.seID == otherKeys.seID && 
      this.pgID == otherKeys.pgID; 
    } 
} 

注:

  • 哈希碼是基於所述單個值的哈希碼來計算。一個乘以37,這只是一個方便的素數;有些人更喜歡使用更大的素數來更好地「混合」。對於大多數情況下,上述將工作正常恕我直言。
  • 請注意,您提出的解決方案,轉換值轉換爲字符串,它們串聯,並返回哈希碼的是有幾個不利的方面:
    • 你必須只創建三個字符串實例來生成散列碼!單獨的內存開銷已經夠糟糕了,但是當然也有格式化這兩個整數的代價。
    • 從字符串生成哈希碼的計算比整數值更昂貴
    • 您有更高的碰撞風險,因爲不同的值更容易導致相同的字符串(例如(11,2222 )和(111,222))
  • 我將readonly添加到您的字段。如果您決定將類型設爲struct(即使您未覆蓋方法),這將是至關重要。但即使對於一個類來說,可變類型也是一個巨大的問題,因爲如果在將它們添加到基於散列的集合之後它們發生更改,則該集合將被有效地破壞。這裏使用readonly確保類型是不可變的。 (另外,應該避免恕我直言的公共領域,但是如果必須擁有它們,即使您不覆蓋相等方法,它們也應該是readonly)。
  • 有些人更喜歡在Equals()方法中檢查確切的類型相等。事實上,這通常是個好主意......它簡化了對象進行比較的場景,並使代碼更易於維護。但是爲了舉例,可分配性(即as)更容易閱讀,並且在許多情況下都是有效的。

請參閱General advice and guidelines on how to properly override object.GetHashCode()以獲取更多指導。

相關問題