天天看點

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

.NET程式員都知道,如果我們重寫一個類的Equals方法而沒有重寫GetHashCode,則VS會提示警告 :“***”重寫 Object.Equals(object o)但不重寫 Object.GetHashCode() 。

但是,為什麼重寫Equals一定要同時重寫GetHashCode呢?

微軟的解釋是:

GetHashCode 基于适合雜湊演算法和諸如哈希表的資料結構的目前執行個體傳回一個值。 兩個相等的同類型對象必須傳回相同的哈希代碼,才能確定以下類型的執行個體正确運作:

  • HashTable
  • System.Collections.SortedList
  • Dictionary
  • SortDictionary
  • SortList
  • HybredDictionary
  • System.Collections.Specialized.ListDictionary
  • System.Collections.Specialized.OrderedDictionary
  • 實作 IEqualityComparer 的類型

連結: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();
        }      

結果:

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

傳回的結果是true,這好像是我們的重寫方法成功了。那我們繼續寫一個測試方法吧。

ICollection<Person> list = new HashSet<Person>();
            list.Add(person1);
            Console.WriteLine("List是否包含person1:"+list.Contains(person1));
            Console.WriteLine("List是否包含person2:" + list.Contains(person2));      
重寫Equals為什麼要同時重寫GetHashCode

這時,就出問題了。既然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();
        }
    }      

再運作兩個測試方法:

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

現在,方法都傳回true了。

還有一個例子,如果将Person類當作鍵值放在字典中也會有問題,可以參見:http://book.51cto.com/art/201109/292340.htm。

重寫GetHashCode的原則很簡單,隻要能保證兩個相等的同類型對象傳回相同的哈希代碼就OK了。

還找到一個說得比較好的地方,裡面第二個評論很精彩。http://blog.csdn.net/chenyuxu0/article/details/5886771

如果我的文章對你有幫助,就點一下推薦吧.(*^__^*)

繼續閱讀