请求注释:字典键的快速哈希基类

时间:2010-08-07 12:31:34

标签: c# performance hash

在我的一个应用中,我必须使用许多带有自定义对象的dictonarys作为键。为了提高查找的性能,我实现了一个重写GetHashCode的基类。 接缝工作,但不知怎的,我仍然有一个不好的感觉,所以我决定发布我的代码,我会感激任何提示或coments。 (omg我忘记了代码:D)

abstract class FastHashed
{
    private static Dictionary<Type,ulong> _instanceCounters = new Dictionary<Type,ulong>();

    private int hash;

    protected FastHashed()
    {
        Type instanceType = this.GetType();
        if(! _instanceCounters.ContainsKey(instanceType)) _instanceCounters.Add(instanceType,0);  
        this.hash = ((instanceType.ToString())+(_instanceCounters[instanceType]++.ToString())).GetHashCode();
    }

    public override int  GetHashCode()
    {
         return hash;
    }
}

编辑:如果你不需要,不要乱用哈希。这个“sollution”比默认的GetHashCode()更慢,更不可靠。

编辑: 我使用Equatec分析器和简单的控制台应用程序进行了一些性能测试。

课程计划     {         static readonly int cycles = 50000;         static Dictionary objectsDict = new Dictionary();         static Dictionary foosDict = new Dictionary();

    static void Main(string[] args)
    {

        foo[] foos = new foo[cycles];
        object[] objects = new object[cycles];


        for (int i = 0; i < cycles; i++)
        {
            foos[i] = new foo();
            objects[i] = new object();
            foosDict.Add(foos[i], i);
            objectsDict.Add(objects[i], i);
        }

        ObjectHash(objects);
        FooHash(foos);

    }

    static void ObjectHash(Object[] objects)
    {
        int value; 
        for (int i = 0; i < cycles; i++)
        {
            value = objectsDict[objects[i]];
        }

    }
    static void FooHash(foo[] foos)
    {
        int value;
        for (int i = 0; i < cycles; i++)
        {
            value = foosDict[foos[i]];
        }
    }

    class foo
    {
        private readonly int _hash;
        public foo()
        {
            _hash = this.GetHashCode();
        }
        public override int GetHashCode()
        {
            return _hash;
        }
    }
}

结果:   - FooHash 26 774 ms   - ObjectHash 7 ms

显然,defhat GetHashCode是最好的选择。

3 个答案:

答案 0 :(得分:2)

  1. 这不是线程安全的。
  2. 如果您只关心引用相等性,为什么不同的类型有不同的计数器?
  3. 如果您想要的是防止Hashes多次计算,为什么不这样(或者如果字典只保存某种类型的对象,则为带泛型的变体):

      public class ObjectWithCachedHashCode : IEquatable<ObjectWithCachedHashCode>
        {
            private int _cachedHashCode;
    
            public object Object { get; private set; }
    
            public ObjectWithCachedHashCode(object obj)
            {
                Object = obj;
                _cachedHashCode = obj.GetHashCode();
            }
    
            public override int GetHashCode()
            {
                return _cachedHashCode;
            }
    
            public bool Equals(ObjectWithCachedHashCode other)
            {
                return other!=null && Object.Equals(other.Object);
            }
    
            public override bool Equals(object other)
            {
                return Equals(other as ObjectWithCachedHashCode);
            }
    
    
        }
    

    编辑:使类与Dictionary

    兼容

答案 1 :(得分:2)

您可以标记哈希变量readonly

但说实话,在C#中你有单一继承,“浪费”继承来实现这种特定的行为并不总是明智的。假设您突然想要从“做”某事的基类继承。将类继承保存到建模目的,而不是实现细节。

答案 2 :(得分:0)

据我所知,这在功能上与object.GetHashCode()默认实现等效,除了速度较慢且非线程安全。什么使“快速哈希”变得快速?