none
怎样让HashTable认为两个同值对象相等? RRS feed

  • 问题

  • 以下是我的代码,其中a1和a3拥有相同的值。两个对象的Equals()方法返回为true,但是用到HashTable中就为False了。
    请问怎样让HashTable认为两个同值对象相等?

    using System;

    namespace ConsoleApplication3
    {
        class Age
        {
            private int _year;
            public Age(int year)
            {
                _year = year;
            }
            public int Year
            {
                get
                {
                    return this._year;
                }
            }
            public override bool Equals(object obj)
            {
                Age a = (Age)obj;
                return a._year == this._year;
            }
            public override int GetHashCode()
            {
                return base.GetHashCode() ^ _year;
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                System.Collections.Hashtable ageList = new System.Collections.Hashtable();
                Age a1 = new Age(123);
                ageList.Add(a1, a1);
                Age a2 = new Age(567);
                ageList.Add(a2,a2);

                Age a3 = new Age(123);

                Console.WriteLine(a1.Year);
                Console.WriteLine(a3.Year);

                bool boolean = a3.Equals(a1);
                Console.WriteLine(boolean);

                bool boolean2 = ageList.Contains(a3);
                Console.WriteLine(boolean2);

                Console.Read();

                /*
                 * 运行结果:
                 * 123
                 * 123
                 * True
                 * False
                 */
            }
        }
    }


    做最好的自己
    2009年8月9日 6:32

答案

  • 你好a3.Equals(a1)是根据你的重载
    public override bool Equals(object obj)
            {
                Age a = (Age)obj;
                return a._year == this._year;
            }
    来判断的 这里的a3的_year和a1的相等都是值类型的int 均为123 因此返回的是true
    但是  bool boolean2 = ageList.Contains(a3); 则是确定这个HashTable是否包含了a3 当你用  bool boolean2 = ageList.Contains(a2);或者 bool boolean2 = ageList.Contains(a1);由于他们都是引用类型,你添加了a1和a2到hashTable的 所以返回为True 但是由于a3你是没有添加的所有返回为false,如果你是要判断HashTable是否存在某个Age对象的实例它的_year和你传入的Age对象的_year相等,可以通过遍历的方式

    bool ContainsAge(Age a)
    {
    foreach(Object htA in ageList.Keys)
    {
    bool contains=(Age)htA.Equals(a);
    if(contains)
    {
    return true;
    }
    }
    return false;
    }
    Wenn ich dich hab’,gibt es nichts, was unerträglich ist.坚持不懈!http://hi.baidu.com/1987raymond
    2009年8月9日 6:47
    版主
  • Hashtable 的key必须是唯一的 不然失去Hashtable的key意义 
    你在hashtable取出对象才能比较
    2009年8月9日 6:56
  • 您好,HashTable的Contains方法是依靠返回的Key对象的哈希值来判断哈希表中是否包含该对象。
    很明显a3不在HashTable中。正确的使用方法应当不是您设计的代码。但有一个小技巧可以达到您希望的效果。
    将public override int GetHashCode()
            {
                return base.GetHashCode() ^ _year;
            }
    改为
    public override int GetHashCode()
            {
                return  _year;
            }
    2009年8月9日 7:14
  • 感谢楼上各位的答复。
    在此我想请教一下“jiyuan”:
    GetHashCode()有什么作用?为什么函数改成那样就可以让HashTable认为两个同值异对象相同呢?
    做最好的自己

    您好,在调用HashTable中的void Add(Object key, Object value)方法添加一个key/value对时,key对象的哈希值也被存储。这个哈希值则是从key对象的GetHashCode()方法中得来。
    而在遍历查询时,会根据这个哈希值做key的比对。可以简单理解为HashTable中的key是由key对象的哈希值来决定的。因此当这个哈希值相等时HashTable就认为比较的两个对象相等。
    如果按我上面给的方法修改,您会发现在您给的例子中,尝试添加a3会失败。因为a1与a3的哈希值相等。HashTable认为对象已存在。
    2009年8月9日 11:57

全部回复

  • 你好a3.Equals(a1)是根据你的重载
    public override bool Equals(object obj)
            {
                Age a = (Age)obj;
                return a._year == this._year;
            }
    来判断的 这里的a3的_year和a1的相等都是值类型的int 均为123 因此返回的是true
    但是  bool boolean2 = ageList.Contains(a3); 则是确定这个HashTable是否包含了a3 当你用  bool boolean2 = ageList.Contains(a2);或者 bool boolean2 = ageList.Contains(a1);由于他们都是引用类型,你添加了a1和a2到hashTable的 所以返回为True 但是由于a3你是没有添加的所有返回为false,如果你是要判断HashTable是否存在某个Age对象的实例它的_year和你传入的Age对象的_year相等,可以通过遍历的方式

    bool ContainsAge(Age a)
    {
    foreach(Object htA in ageList.Keys)
    {
    bool contains=(Age)htA.Equals(a);
    if(contains)
    {
    return true;
    }
    }
    return false;
    }
    Wenn ich dich hab’,gibt es nichts, was unerträglich ist.坚持不懈!http://hi.baidu.com/1987raymond
    2009年8月9日 6:47
    版主
  • Hashtable 的key必须是唯一的 不然失去Hashtable的key意义 
    你在hashtable取出对象才能比较
    2009年8月9日 6:56
  • 您好,HashTable的Contains方法是依靠返回的Key对象的哈希值来判断哈希表中是否包含该对象。
    很明显a3不在HashTable中。正确的使用方法应当不是您设计的代码。但有一个小技巧可以达到您希望的效果。
    将public override int GetHashCode()
            {
                return base.GetHashCode() ^ _year;
            }
    改为
    public override int GetHashCode()
            {
                return  _year;
            }
    2009年8月9日 7:14
  • 感谢楼上各位的答复。
    在此我想请教一下“jiyuan”:
    GetHashCode()有什么作用?为什么函数改成那样就可以让HashTable认为两个同值异对象相同呢?
    做最好的自己
    2009年8月9日 10:49
  • 感谢楼上各位的答复。
    在此我想请教一下“jiyuan”:
    GetHashCode()有什么作用?为什么函数改成那样就可以让HashTable认为两个同值异对象相同呢?
    做最好的自己

    您好,在调用HashTable中的void Add(Object key, Object value)方法添加一个key/value对时,key对象的哈希值也被存储。这个哈希值则是从key对象的GetHashCode()方法中得来。
    而在遍历查询时,会根据这个哈希值做key的比对。可以简单理解为HashTable中的key是由key对象的哈希值来决定的。因此当这个哈希值相等时HashTable就认为比较的两个对象相等。
    如果按我上面给的方法修改,您会发现在您给的例子中,尝试添加a3会失败。因为a1与a3的哈希值相等。HashTable认为对象已存在。
    2009年8月9日 11:57