C# 使用long(int64)作为哈希代码,并且仍然使用IEqualityComparer作为并发字典

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 {

我在并发字典中使用自制的IEqualityComparer和GetHashCode时遇到问题

下面的类(通过使用两个属性简化)在我这样实现它时工作得非常完美:

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,值);
}
}
这样,您将有一个哈希代码列表,每个哈希代码将再次有一个哈希代码列表,其组合是唯一的。任何