Object.GetHashCode [英] Object.GetHashCode

查看:158
本文介绍了Object.GetHashCode的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题可重复默认实现)但我再次问,因为我不明白接受的答案那一个。

My question may duplicate Default implementation for Object.GetHashCode() but I'm asking again because I didn't understand the accepted answer to that one.

要开始我对的接受的答案前面的问题,该报价一些文档如下:

To begin with I have three questions about the accepted answer to the previous question, which quotes some documentation as follows:

然而,由于垃圾收集期间的对象被回收后这个索引可以重复使用,这是能够获得两个不同的对象相同的哈希码。

"However, because this index can be reused after the object is reclaimed during garbage collection, it is possible to obtain the same hash code for two different objects."

这是真的吗?在我看来,直到该对象被垃圾回收(即不再存在)两个对象不会有相同的散列码,因为对象的代码不重用。

Is this true? It seems to me that two objects won't have the same hash code, because an object's code isn't reused until the object is garbage collected (i.e. no longer exists).

还有,表示相同值的两个对象只有当他们是完全相同的对象相同的散列码。

"Also, two objects that represent the same value have the same hash code only if they are the exact same object."

这是一个问题吗?例如,我想一些数据与每一个DOM树的节点实例相关联。要做到这一点,节点必须有一个身份或哈希码,这样我就可以在数据字典中使用它们作为键。是不是哈希码是否是完全相同的对象,即参考平等,而不是价值平等,我想什么它的身份?

Is this a problem? For example, I want to associate some data with each of the node instances in a DOM tree. To do this, the 'nodes' must have an identity or hash code, so that I can use them as keys in a dictionary of the data. Isn't a hash code which identities whether it's "the exact same object", i.e. "reference equality rather than "value equality", what I want?

此实现不为散列特别有用的;因此,派生类应重写GetHashCode

"This implementation is not particularly useful for hashing; therefore, derived classes should override GetHashCode"

这是真的吗?如果是不好的散列,那么什么如果有的话有什么好处,为什么是它甚至被定义为对象的方法?

Is this true? If it's not good for hashing, then what if anything is it good for, and why is it even defined as a method of Object?

我的最后(或许也是最重要的是我)问题是的,如果我必须发明/覆盖具有参考平等的语义任意类型的GetHashCode()实现,在以下合理和良好的执行:

My final (and perhaps most important to me) question is, if I must invent/override a GetHashCode() implementation for an arbitrary type which has "reference equality" semantics, is the following a reasonable and good implementation:

class SomeType
{
  //create a new value for each instance
  static int s_allocated = 0;
  //value associated with this instance
  int m_allocated;
  //more instance data
  ... plus other data members ...
  //constructor
  SomeType()
  {
    allocated = ++s_allocated;
  }
  //override GetHashCode
  public override int GetHashCode()
  {
    return m_allocated;
  }
}






修改

FYI我测试了它,使用下面的代码:

FYI I tested it, using the following code:

    class TestGetHash
    {
        //default implementation
        class First
        {
            int m_x;
        }
        //my implementation
        class Second
        {
            static int s_allocated = 0;
            int m_allocated;
            int m_x;
            public Second()
            {
                m_allocated = ++s_allocated;
            }
            public override int GetHashCode()
            {
                return m_allocated;
            }
        }
        //stupid worst-case implementation
        class Third
        {
            int m_x;
            public override int GetHashCode()
            {
                return 0;
            }
        }

        internal static void test()
        {
            testT<First>(100, 1000);
            testT<First>(1000, 100);
            testT<Second>(100, 1000);
            testT<Second>(1000, 100);
            testT<Third>(100, 100);
            testT<Third>(1000, 10);
        }

        static void testT<T>(int objects, int iterations)
            where T : new()
        {
            System.Diagnostics.Stopwatch stopWatch =
                System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < iterations; ++i)
            {
                Dictionary<T, object> dictionary = new Dictionary<T, object>();
                for (int j = 0; j < objects; ++j)
                {
                    T t = new T();
                    dictionary.Add(t, null);
                }
                for (int k = 0; k < 100; ++k)
                {
                    foreach (T t in dictionary.Keys)
                    {
                        object o = dictionary[t];
                    }
                }
            }
            stopWatch.Stop();
            string stopwatchMessage = string.Format(
                "Stopwatch: {0} type, {1} objects, {2} iterations, {3} msec",
                typeof(T).Name, objects, iterations,
                stopWatch.ElapsedMilliseconds);
            System.Console.WriteLine(stopwatchMessage);
        }
    }

在我的机器的结果/输出如下:

On my machine the results/output are as follows:

First type, 100 objects, 1000 iterations, 2072 msec
First type, 1000 objects, 100 iterations, 2098 msec
Second type, 100 objects, 1000 iterations, 1300 msec
Second type, 1000 objects, 100 iterations, 1319 msec
Third type, 100 objects, 100 iterations, 1487 msec
Third type, 1000 objects, 10 iterations, 13754 msec

我的实现需要的默认实现一半的时间(但我喜欢的类型是我m_allocated数据成员的大小)大。

My implementation takes half the time of the default implementation (but my type is bigger by the size of my m_allocated data member).

我的实现和默认实现两者的规模呈线性。

My implementation and the default implementation both scale linearly.

在比较和完整性检查,愚蠢的实施开始坏的尺度变得更糟。

In comparison and as a sanity check, the stupid implementation starts bad and scales worse.

推荐答案

最重要物业的哈希码的实施必须有是这样的:

The most important property a hash code implementation must have is this:

如果两个对象的比较结果相等则它们必须有相同的散列码

如果你有一个类,其中通过引用相等比较类的实例,那么你就不需要重写GetHashCode;默认的实现保证了两个对象是相同的附图具有相同的散列码。 (你两次调用同一个对象的同一个方法,所以当然的结果是一样的。)

If you have a class where instances of the class compare by reference equality, then you do not need to override GetHashCode; the default implementation guarantees that two objects that are the same reference have the same hash code. (You're calling the same method twice on the same object, so of course the result is the same.)

如果你写了一个实现自己的平等一类这不同于引用相等,那么你需要重写GetHashCode使得两个是比较平等具有相等的哈希码的对象。

If you have written a class which implements its own equality that is different from reference equality then you are REQUIRED to override GetHashCode such that two objects that compare as equal have equal hash codes.

现在,你可以通过简单地返回这样做零每次。这将是一个糟糕的哈希函数,但它是合法的。

Now, you could do so by simply returning zero every time. That would be a lousy hash function, but it would be legal.

的好的哈希函数的其他属性是:

Other properties of good hash functions are:


  • GetHashCode的应从来没有抛出异常

  • GetHashCode should never throw an exception

这对于比较他们的可变状态的平等,因此对他们的可变状态乱码,是危险的容易出错的可变对象。你可以把一个对象放入一个哈希表,它发生变异,并无法再次把它弄出来。尝试从来没有哈希或比较对可变状态平等

Mutable objects which compare for equality on their mutable state, and therefore hash on their mutable state, are dangerously bug-prone. You can put an object into a hash table, mutate it, and be unable to get it out again. Try to never hash or compare for equality on mutable state.

GetHashCode的应该是非常快 - 还记得,一个好的哈希算法的目的是为了提高查找的性能。如果哈希慢则查找无法进行快。

GetHashCode should be extremely fast -- remember, the purpose of a good hash algorithm is to improve the performance of lookups. If the hash is slow then the lookups can't be made fast.

不比较平等应该有不同的散列码的对象,以及分布在一个32位整数

Objects which do not compare as equal should have dissimilar hash codes, well distributed over the whole range of a 32 bit integer

这篇关于Object.GetHashCode的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆