码迷,mamicode.com
首页 > 其他好文 > 详细

【转】重写Equals为什么要同时重写GetHashCode

时间:2017-02-06 19:30:52      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:sorted   uid   ros   ddc   html   microsoft   ble   rri   soft   

.NET程序员都知道,如果我们重写一个类的Equals方法而没有重写GetHashCode,则VS会提示警告 :“***”重写 Object.Equals(object o)但不重写 Object.GetHashCode() 。

但是,为什么重写Equals一定要同时重写GetHashCode呢?

微软的解释是:

GetHashCode 基于适合哈希算法和诸如哈希表的数据结构的当前实例返回一个值。 两个相等的同类型对象必须返回相同的哈希代码,才能确保以下类型的实例正确运行:

链接:http://msdn.microsoft.com/zh-cn/library/vstudio/ms182358.aspx

举个例子:

重写一个Person类

技术分享
 public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        /// <summary>
        /// 重写Equals,如果Name与Age相等,就认为类相等
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            if (obj is Person)
            {
                var person = obj as Person;
                return person.Age == this.Age && person.Name == this.Name;
            }
            else
                return false;
        }
    }
技术分享

写一个测试方法:

技术分享
  public  static void Main(string[] args)
        {
            Person person1 = new Person() { Id = 1, Name = "AA", Age = 21 };
            Person person2 = new Person() { Id = 2, Name = "AA", Age = 21 };
            
            Console.WriteLine("person1与person2是否相等:" + person1.Equals(person2));
            Console.Read();
        }
技术分享

结果:

技术分享

返回的结果是true,这好像是我们的重写方法成功了。那我们继续写一个测试方法吧。

            ICollection<Person> list = new HashSet<Person>();
            list.Add(person1);
            Console.WriteLine("List是否包含person1:"+list.Contains(person1));
            Console.WriteLine("List是否包含person2:" + list.Contains(person2));

结果:

技术分享

这时,就出问题了。既然person1与person2相等,list它包含person1,那也应该包含person2吧。原因就是我们没有重写GetHashCode方法,相同的对象没有返回相等的HashCode。

我们重新改变一下Person,让它重写GetHashCode方法。

技术分享
 public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        /// <summary>
        /// 重写Equals,如果Name与Age相等,就认为类相等
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            if (obj is Person)
            {
                var person = obj as Person;
                return person.Age == this.Age && person.Name == this.Name;
            }
            else
                return false;
        }

        public override int GetHashCode()
        {
            return this.Name.GetHashCode()^this.Age.GetHashCode();
        }
    }
技术分享

再运行两个测试方法:

技术分享

现在,方法都返回true了。

还有一个例子,如果将Person类当作键值放在字典中也会有问题,可以参见:http://book.51cto.com/art/201109/292340.htm

重写GetHashCode的原则很简单,只要能保证两个相等的同类型对象返回相同的哈希代码就OK了。

还找到一个说得比较好的地方,里面第二个评论很精彩。http://blog.csdn.net/chenyuxu0/article/details/5886771

【转】重写Equals为什么要同时重写GetHashCode

标签:sorted   uid   ros   ddc   html   microsoft   ble   rri   soft   

原文地址:http://www.cnblogs.com/x-poior/p/6371354.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!