我有一個問題,在併發字典中使用自制的IEqualityComparer和GetHashCode。使用long(int64)作爲hashCode,並仍然使用IEqualityComparer併發Dictionary
ConcurrentDictionary<TwoUintsKeyInfo,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfo, Int64>();
:
下面的類(使用提供的兩個特性簡化),當我實現它這樣完美的作品。
public class TwoUintsKeyInfo
{
public uint IdOne { get; set; }
public uint IdTwo { get; set; }
#region Implemetation of the IEqualityComparer
public class EqualityComparerTwoUintsKeyInfo : IEqualityComparer<TwoUintsKeyInfo>
{
System.Reflection.PropertyInfo[] properties;
bool propertyArraySet=false;
public int GetHashCode(TwoUintsKeyInfo obj)
{
unchecked
{
if(!propertyArraySet)
{
properties = obj.GetType().GetProperties().OrderBy(x => x.Name).ToArray();
propertyArraySet = true;
}
decimal hash = 17;
int counter=0;
foreach(System.Reflection.PropertyInfo p in properties)
{
counter++;
var value = p.GetValue(obj);
decimal unique = (decimal)Math.Pow(Math.E, counter);
hash = hash + (value == null ? unique : value.GetHashCode() * unique);
}
return 2147483647M * .001M > hash ? (int)(hash * 1000) : (int)hash;
}
}
public bool Equals(TwoUintsKeyInfo x, TwoUintsKeyInfo y)
{
return GetHashCode(x) == GetHashCode(y);
}
}
#endregion Implemetation of the IEqualityComparer
}
現在我做了幾乎相同的類,但不是正常的IEqualityComparer接口,我做了一個小的變化,所以我可能會產生長/ Int64的hascodes(因爲上課的時候持有越來越多的特性,我們遇到具有相同哈希碼的多個值)
所以我想減少獲得相同hascode的變化。因此,我想使用更大的數字,如果可能的話使用10000以上的倍數來獲取動作中的一些小數。
所以我創造了這個接口:
public interface IEqualityComparerInt64<in T>
{
bool Equals(T x, T y);
Int64 GetHashCode(T obj);
}
,並改變了性質類,所以它看起來像這樣:
public class TwoUintsKeyInfoInt64
{
public uint IdOne { get; set; }
public uint IdTwo { get; set; }
#region Implemetation of the IEqualityComparer
public class EqualityComparerTwoUintsKeyInfoInt64 : IEqualityComparerInt64<TwoUintsKeyInfoInt64>
{
System.Reflection.PropertyInfo[] properties;
bool propertyArraySet=false;
decimal _upperThreshold,_lowerThreshold;
public EqualityComparerTwoUintsKeyInfoInt64()
{
_upperThreshold = long.MaxValue * .0001M;
_lowerThreshold = -long.MaxValue * .0001M;
}
public long GetHashCode(TwoUintsKeyInfoInt64 obj)
{
unchecked
{
if(!propertyArraySet)
{
properties = obj.GetType().GetProperties().OrderBy(x => x.Name).ToArray();
propertyArraySet = true;
}
decimal hash = 17;
int counter=0;
foreach(System.Reflection.PropertyInfo p in properties)
{
counter++;
var value = p.GetValue(obj);
decimal unique = (decimal)Math.Pow(Math.E, counter);
hash = hash + (value == null ? unique : value.GetHashCode() * unique);
}
return _upperThreshold > hash && _lowerThreshold < hash ? (long)(hash * 10000) : (long)hash;
}
}
public bool Equals(TwoUintsKeyInfoInt64 x, TwoUintsKeyInfoInt64 y)
{
return GetHashCode(x) == GetHashCode(y);
}
}
#endregion Implemetation of the IEqualityComparer
}
GetHashCode的正常工作。到目前爲止沒有問題。
但是...當我嘗試到的IEqualityComparer添加到concurrentdictionary這樣的:
ConcurrentDictionary<TwoUintsKeyInfoInt64,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfoInt64, Int64>(new TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo());
我得到這個錯誤:
Error 3 Argument 1: cannot convert from 'HasCodeTestForUniqueResult.TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo' to 'System.Collections.Generic.IEqualityComparer' D:\Users\mldz\Documents\visual studio 2012\HashCodeTestForUniqueResult\HashCodeTestForUniqueResult\Form1.cs 109 140 HashCodeTestForUniqueResult
據我所知,有int類型之間的衝突默認的System.Collections.Generic.IEqualityComparer和我自己的GetHashCode生成器的long/int64結果。但是有沒有什麼辦法可以解決這個問題,並且可以使用長的HashCodes?
親切的問候,
Matthijs
附:上面的代碼只是爲了測試它並重現問題。
爲什麼要長時間創建自己的數據類型? (參考TwoUintsKeyInfoInt64) – Matthew
你是什麼意思?我想讓GetHashCode更精確(閱讀:減少對具有相同哈希碼的不同值的更改) – user369122
作爲一個方面說明,這是不好的:'公共布爾等於(TwoUintsKeyInfo x,TwoUintsKeyInfo y){return GetHashCode(x) == GetHashCode(y); }'。正如你自己指出的那樣,相同的哈希碼並不一定意味着這兩個對象是相同的。如果兩個對象完全相同,那麼Equal只應該返回「true」。 –