user4981830
user4981830

Reputation:

C# Implementing the Equals Method Correctly and How do I implement the GetHashCode Method

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 
        }
        */ 
    }
}

I was following the guidelines by MSDN. Two questions:

  1. Have I correctly implemented the equals method?
  2. Could someone show me how to implement GetHashCode Correctly for my class? MSDN does x ^ y, but I can't do it for mine.

Upvotes: 6

Views: 152

Answers (3)

user743382
user743382

Reputation:

A more common method than a simple xor of hash codes, as posted in Filip's answer, is to use a more complicated formula to combine them. Multiply the individual fields' hash codes by different numbers, for example like so:

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

(Note the unchecked keyword: integer overflow is expected here, and silent wraparound is exactly the intended behaviour.)

It probably won't make a difference for the concrete types you're dealing with, but in general, it's better. Consider a simple type containing only two integer values. Consider also that int's GetHashCode() implementation simply returns its own value. If you use a simple xor to combine the values, you will have a lot of hash collisions for normal code: the simplest example is that each pair of two identical values will produce the same hash code of zero.

The calculation here is actually the calculation that's done by Tuple<T1, T2, T3>. I didn't write it the way Microsoft did, but the actual calculations and numbers should be the same.

Upvotes: 1

Christoph Grimmer
Christoph Grimmer

Reputation: 4323

Best keep in mind what the purpose of these two methods is: With equals YOU define under which circumstances two instances of your class should be treated as, well, equal. So if in your case this is given iff first name, last name and phone number are equal then this is correct. The hash method in turn is used to sort or distribute you instances e.g. in a hash map. It should be fast and good enough to avoid unwanted clustering. Therefore you often see values multiplied by a prime in hash functions. You have to guarantee that equal objects have the same hash code but not vice versa. So different objects may have the same hash code.

Upvotes: 1

Filip
Filip

Reputation: 1864

Well, to not run into any problems, GetHashCode should use all the members that Equals uses and vice versa.

So in your case:

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

Upvotes: 6

Related Questions