如何C#弄清楚的哈希代码的对象? [英] How does c# figure out the hash code for an object?

查看:148
本文介绍了如何C#弄清楚的哈希代码的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题出来讨论上的元组

This question comes out of the discussion on tuples.

我开始思考的散列码元组应该有。
如果我们将接受KeyValuePair类作为一个元组?它不会覆盖的GetHashCode()方法,所以可能不会意识到它的孩子的哈希码的...因此,运行时将调用Object.GetHashCode(),这是不知道的真正的对象结构。

I started thinking about the hash code that a tuple should have. What if we will accept KeyValuePair class as a tuple? It doesn't override the GetHashCode() method, so probably it won't be aware of the hash codes of it's "children"... So, run-time will call Object.GetHashCode(), which is not aware of the real object structure.

然后,我们可以做一些引用类型的两个实例,这实际上是平等的,因为超载的GetHashCode()和equals()。而在元组使用它们作为孩子来欺骗的字典。

Then we can make two instances of some reference type, which are actually Equal, because of the overloaded GetHashCode() and Equals(). And use them as "children" in tuples to "cheat" the dictionary.

不过,这是行不通的!运行时莫名其妙地计算出我们的元组的结构,并调用类的重载GetHashCode的!

But it doesn't work! Run-time somehow figures out the structure of our tuple and calls the overloaded GetHashCode of our class!

它是如何工作的?什么是由Object.GetHashCode()所做的分析?

How does it work? What's the analysis made by Object.GetHashCode()?

这可能会影响一些不好的情况下的表现,当我们使用一些复杂的钥匙? (可能,不可能的场景......但还是)

Can it affect the performance in some bad scenario, when we use some complicated keys? (probably, impossible scenario... but still)

考虑以下代码为例:

namespace csharp_tricks
{
    class Program
    {
        class MyClass
        {
            int keyValue;
            int someInfo;

            public MyClass(int key, int info)
            {
                keyValue = key;
                someInfo = info;
            }

            public override bool Equals(object obj)
            {
                MyClass other = obj as MyClass;
                if (other == null) return false;

                return keyValue.Equals(other.keyValue);
            }

            public override int GetHashCode()
            {
                return keyValue.GetHashCode();
            }
        }

        static void Main(string[] args)
        {
            Dictionary<object, object> dict = new Dictionary<object, object>();

            dict.Add(new KeyValuePair<MyClass,object>(new MyClass(1, 1), 1), 1);

            //here we get the exception -- an item with the same key was already added
            //but how did it figure out the hash code?
            dict.Add(new KeyValuePair<MyClass,object>(new MyClass(1, 2), 1), 1); 

            return;
        }
    }
}



更新我想我已经找到了一个这样的解释我的回答如下所述。它的主要成果是:

Update I think I've found an explanation for this as stated below in my answer. The main outcomes of it are:


  • 小心你的钥匙和他们的哈希码: - )

  • 复杂字典键,你必须重载equals()和GetHashCode()正确。

推荐答案

看来,我有一个线索了。

It seems that I have a clue now.

我想KeyValuePair是引用类型,但它不是,它是一个结构。并因此它使用ValueType.GetHashCode()方法。 MSDN它说:派生类型的一个或多个字段被用来计算返回值

I thought KeyValuePair is a reference type, but it is not, it is a struct. And so it uses ValueType.GetHashCode() method. MSDN for it says: "One or more fields of the derived type is used to calculate the return value".

如果您需要一个真正的引用类型为元组。-provider你骗词典(或自己...)

If you will take a real reference type as a "tuple-provider" you'll cheat the dictionary (or yourself...).

using System.Collections.Generic;

namespace csharp_tricks
{
    class Program
    {
        class MyClass
        {
            int keyValue;
            int someInfo;

            public MyClass(int key, int info)
            {
                keyValue = key;
                someInfo = info;
            }

            public override bool Equals(object obj)
            {
                MyClass other = obj as MyClass;
                if (other == null) return false;

                return keyValue.Equals(other.keyValue);
            }

            public override int GetHashCode()
            {
                return keyValue.GetHashCode();
            }
        }

        class Pair<T, R>
        {
            public T First { get; set; }
            public R Second { get; set; }
        }

        static void Main(string[] args)
        {
            var dict = new Dictionary<Pair<int, MyClass>, object>();

            dict.Add(new Pair<int, MyClass>() { First = 1, Second = new MyClass(1, 2) }, 1);

            //this is a pair of the same values as previous! but... no exception this time...
            dict.Add(new Pair<int, MyClass>() { First = 1, Second = new MyClass(1, 3) }, 1);

            return;
        }
    }
}

这篇关于如何C#弄清楚的哈希代码的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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