重寫Equals為什么要同時重寫GetHashCode


.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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM