【轉】重寫Equals爲何要同時重寫GetHashCode

.NET程序員都知道,若是咱們重寫一個類的Equals方法而沒有重寫GetHashCode,則VS會提示警告 :「***」重寫 Object.Equals(object o)但不重寫 Object.GetHashCode() 。html

可是,爲何重寫Equals必定要同時重寫GetHashCode呢?git

微軟的解釋是:程序員

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

若是個人文章對你有幫助,就點一下推薦吧.(*^__^*)
 
 
標籤:  .NET
好文要頂  關注我  收藏該文   
4
0
 
 
 
« 上一篇: ghost xp 安裝IIS,並配置WCF
» 下一篇: WCF錯誤:413 Request Entity Too Large
posted @  2013-08-12 22:49 Gyoung 閱讀(2608) 評論(4) 編輯 收藏

 

 
#1樓   2013-08-13 09:03 懼怕飛的鳥  
可是本身寫這個函數的時候貌似還得注意hash碰撞的問題。。。不然。。。容易出現哈希碰撞拒絕服務攻擊。。。
相關文章
相關標籤/搜索