C#正确实现Equals方法,如何实现GetHashCode方法

时间:2015-06-07 11:40:55

标签: c#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Crystal_Message
{
    class Person
    {
        private string firstName ="";
        private string lastName= "";
        private string phone="";


        public Person(string firstName, string lastName, string phone)
        {
            this.FirstName = firstName;
            this.LastName = lastName;
            this.PhoneNumber = phone;
        }

        public string FirstName
        {
            get { return firstName; }

            private set
            {
                if (string.IsNullOrWhiteSpace(value)){

                    throw new ArgumentNullException("Must Include First Name");
                }

                this.firstName = value;
            }

        }

        public string LastName
        {
            get { return lastName; }

            private set
            {
                if (string.IsNullOrWhiteSpace(value)){

                    throw new ArgumentNullException("Must Include Last Name");
                }

                this.lastName = value;
            }

        }

        public string PhoneNumber
        {
            get { return phone; }

            private set
            {
                if (string.IsNullOrWhiteSpace(value)){

                    throw new ArgumentNullException("Must Include Phone Number");
                }

                this.phone = value;
            }

        }


        public override string ToString()
        {
            return "First Name: " + this.FirstName + " " + " Last Name: " + this.LastName + " " + " Phone Number: " + this.PhoneNumber;
        }

        public override bool Equals(object obj)
        {
            if(obj == null)
            {
                return false;
            }

            Person testEquals = obj as Person;

            if((System.Object)testEquals == null)
            {
                return false;
            }

            return (this.firstName == testEquals.firstName) && (this.lastName == testEquals.lastName) && (this.phone == testEquals.phone);   

        }

        /*
        public override int GetHashCode()
        {
           return 
        }
        */ 
    }
}

我遵循了MSDN的指导原则。两个问题:

  1. 我是否正确实施了equals方法?
  2. 有人可以告诉我如何正确地为我的班级实现GetHashCode吗? MSDN做x ^ y,但我不能为我做。

3 个答案:

答案 0 :(得分:6)

好吧,为了避免遇到任何问题,GetHashCode应该使用Equals使用的所有成员,反之亦然。

所以在你的情况下:

public override int GetHashCode()
{
    return firstName.GetHashCode() ^ lastName.GetHashCode() ^ phone.GetHashCode();
}

答案 1 :(得分:1)

最好记住这两种方法的目的是什么: 使用equals您可以定义在哪种情况下,您的类的两个实例应该被视为相等。因此,如果在您的情况下给出iff名字,姓氏和电话号码相等,那么这是正确的。 反过来,哈希方法用于对实例进行排序或分发,例如在哈希映射中。它应该快速且足够好以避免不必要的群集。因此,您经常会看到值乘以散列函数中的素数。 您必须保证相等的对象具有相同的哈希码,但反之则不然。因此,不同的对象可能具有相同的哈希码。

答案 2 :(得分:1)

一个比简单的哈希码xor更常见的方法,如Filip的答案所述,是使用更复杂的公式来组合它们。将各个字段的哈希码乘以不同的数字,例如:

public override int GetHashCode()
{
    unchecked
    {
        return (firstName.GetHashCode() * 33 ^ lastName.GetHashCode()) * 33 ^ phone.GetHashCode();
    }
}

(注意unchecked关键字:此处需要整数溢出,而无声环绕正是预期的行为。)

对于您正在处理的具体类型可能没有什么区别,但总的来说,它更好。考虑一个只包含两个整数值的简单类型。还要考虑int的{​​{1}}实现只返回自己的值。如果使用简单的xor来组合这些值,那么普通代码会产生大量的哈希冲突:最简单的例子是每对两个相同的值将产生相同的零哈希码。

此处的计算实际上是由GetHashCode()完成的计算。我没有像微软那样写它,但实际的计算和数字应该是一样的。

相关问题