C# 使用long(int64)作为哈希代码,并且仍然使用IEqualityComparer作为并发字典
我在并发字典中使用自制的IEqualityComparer和GetHashCode时遇到问题 下面的类(通过使用两个属性简化)在我这样实现它时工作得非常完美:C# 使用long(int64)作为哈希代码,并且仍然使用IEqualityComparer作为并发字典,c#,hash,gethashcode,iequalitycomparer,concurrentdictionary,C#,Hash,Gethashcode,Iequalitycomparer,Concurrentdictionary,我在并发字典中使用自制的IEqualityComparer和GetHashCode时遇到问题 下面的类(通过使用两个属性简化)在我这样实现它时工作得非常完美: ConcurrentDictionary<TwoUintsKeyInfo,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfo, Int64>(); public class TwoUintsKeyInfoInt64 {
ConcurrentDictionary<TwoUintsKeyInfo,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfo, Int64>();
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
}
ConcurrentDictionary<TwoUintsKeyInfoInt64,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfoInt64, Int64>(new TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo());
ConcurrentDictionary hashCodePlusIandJDict=new ConcurrentDictionary();
public类TwoUintsKeyInfo
{
公共uint IdOne{get;set;}
公共uint IdTwo{get;set;}
#IEqualityComparer的区域实现
公共类EqualityComparerTwoUintsKeyInfo:IEqualityComparer
{
System.Reflection.PropertyInfo[]属性;
bool propertyArraySet=false;
public int GetHashCode(TwoUintsKeyInfo对象)
{
未经检查
{
如果(!PropertyArray集)
{
properties=obj.GetType().GetProperties().OrderBy(x=>x.Name.ToArray();
propertyArraySet=true;
}
十进制散列=17;
int计数器=0;
foreach(System.Reflection.PropertyInfo p in properties)
{
计数器++;
var值=p.GetValue(obj);
十进制唯一=(十进制)Math.Pow(Math.E,计数器);
hash=hash+(value==null?唯一:value.GetHashCode()*唯一);
}
返回2147483647M*.001M>散列?(int)(散列*1000):(int)散列;
}
}
公共布尔等于(TwoUintsKeyInfo x,TwoUintsKeyInfo y)
{
返回GetHashCode(x)==GetHashCode(y);
}
}
#IEqualityComparer的端域实现
}
现在,我创建了几乎相同的类,但没有使用普通的IEqualityComparer接口,而是做了一些更改,这样我就可以生成long/int64 hascodes(因为当类包含越来越多的属性时,我们会遇到使用相同hashcode的多个值)
因此,我想减少获得相同hascode的更改。因此,我想使用更大的数字,如果可能的话,乘以10000,以便在动作中获得一些小数
因此,我创建了这个界面:
public interface IEqualityComparerInt64<in T>
{
bool Equals(T x, T y);
Int64 GetHashCode(T obj);
}
公共接口IEQualityComparePrint64
{
bool等于(tx,ty);
Int64 GetHashCode(T obj);
}
并更改了属性类,使其如下所示:
ConcurrentDictionary<TwoUintsKeyInfo,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfo, Int64>();
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
}
ConcurrentDictionary<TwoUintsKeyInfoInt64,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfoInt64, Int64>(new TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo());
公共类TwoUintsKeyInfoInt64
{
公共uint IdOne{get;set;}
公共uint IdTwo{get;set;}
#IEqualityComparer的区域实现
公共类EqualityCompareWouintSkeyInput64:IEqualityComparePrint64
{
System.Reflection.PropertyInfo[]属性;
bool propertyArraySet=false;
十进制_上限阈值_下限阈值;
公共平等公司不受限制的文件64()
{
_上限阈值=长.MaxValue*.0001M;
_lowerThreshold=-long.MaxValue*.0001M;
}
公共长GetHashCode(TwoUintsKeyInfoInt64 obj)
{
未经检查
{
如果(!PropertyArray集)
{
properties=obj.GetType().GetProperties().OrderBy(x=>x.Name.ToArray();
propertyArraySet=true;
}
十进制散列=17;
int计数器=0;
foreach(System.Reflection.PropertyInfo p in properties)
{
计数器++;
var值=p.GetValue(obj);
十进制唯一=(十进制)Math.Pow(Math.E,计数器);
hash=hash+(value==null?唯一:value.GetHashCode()*唯一);
}
返回_upperThreshold>hash&&u lowerThreshold
GetHashCode运行良好。到目前为止没有问题
但是…当我尝试向concurrentdictionary添加IEqualityComparer时,如下所示:
ConcurrentDictionary<TwoUintsKeyInfo,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfo, Int64>();
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
}
ConcurrentDictionary<TwoUintsKeyInfoInt64,Int64> hashCodePlusIandJDict = new ConcurrentDictionary<TwoUintsKeyInfoInt64, Int64>(new TwoUintsKeyInfoInt64.EqualityComparerOneUintAndTwoStringKeyInfo());
ConcurrentDictionary HashCodePlusia和JDict=新的ConcurrentDictionary(新的TwoUintsKeyInfoInt64.EqualityCompareRoneIntandTwoStringKeyInfo());
我得到这个错误:
错误3参数1:无法从转换
'HasCodeTestForUniqueResult.TwoUintsKeyInfoInt64.EqualityCompareRonInInt和TwoStringKeyInfo'
到
'System.Collections.Generic.IEqualityComparer'D:\Users\mldz\Documents\visual
演播室
2012\HashCodeTestForUniqueResult\HashCodeTestForUniqueResult\Form1.cs 109 140 HashCodeTestForUniqueResult
我知道默认System.Collections.Generic.IEqualityComparer的int类型与我自己的GetHashCode生成器的long/int64结果之间存在冲突。但是有没有办法解决这个问题,并且能够使用长哈希代码呢
亲切问候,
马提斯
另外,上面的代码只是为了测试它并复制问题 根据你的说法,你不能使用长哈希码,所以这个问题的答案是否定的
但你可以有独特的组合,而不是独特的价值观;解决方案是实现一个分区系统,这意味着有一个字典字典,如:
public class MyClass
{
Dictionary<uint, Dictionary<uint, Int64>> PartDict;
Int64 ReadValue(uint id1, uint id2)
{
return (PartDict[id1])[id2];
}
void AddValue(uint id1, uint id2, Int64 value)
{
Dictionary<uint, Int64> container;
if (!PartDict.TryGetValue(id1, out container))
{
container = new Dictionary<uint, Int64>();
PartDict.Add(id1, container);
}
container.Add(id2, value);
}
}
公共类MyClass
{
词典部分词典;
Int64读取值(uint id1、uint id2)
{
返回(PartDict[id1])[id2];
}
无效添加值(uint id1、uint id2、Int64值)
{
字典容器;
if(!PartDict.TryGetValue(id1,输出容器))
{
容器=新字典();
PartDict.Add(id1,容器);
}
容器。添加(id2,值);
}
}
这样,您将有一个哈希代码列表,每个哈希代码将再次有一个哈希代码列表,其组合是唯一的。任何