palermo4 posted on April 1, 2010 12:08

The following example demonstrates a simple class (Student) that implements the necessary code to establish equality between itself and another instance of Student:

public class Student : IEquatable<Student>
{
    public int StudentID { get; set; }
    public string FullName { get; set; }

    public override string ToString()
    {
        return string.Format("{0}: {1}",
            StudentID, FullName);
    }// method

    public override int GetHashCode()
    {
        return this.StudentID;
    }// method

    public override bool Equals(object obj)
    {
        Student other = obj as Student;
        return ((IEquatable<Student>)this).Equals(other);
    }// method

    bool IEquatable<Student>.Equals(Student other)
    {
        if (object.Equals(other, null)) return false;
        return (GetHashCode() == other.GetHashCode());
    }// explicit interface implementation

    public static bool operator ==(Student s1, Student s2)
    {
        if (Object.Equals(s1,null))
            return (Object.Equals(s2,null));
            return ((IEquatable<Student>)s1).Equals(s2);
    }// operator overload

    public static bool operator !=(Student s1, Student s2)
    {
        return !(s1 == s2);
    }// operator overload

}// class

Posted in: code  Tags:

Comments


April 1. 2010 18:26
I disagree with your example for a few reasons. You should only implement IEquatable<T> and override Object.Equals() and Object.GetHashCode() on an immutable object that has value-type semantics. For a mutable object, you're better off not implementing value-based equality and instead relying on the default behavior of Object.Equals() that performs by-reference comparisons of the object's location in memory.

In your example above, you're also returning the student id as the hash code. This is a big problem because the StudentID property is mutable with a setter. Thus if you insert this object into a hash table and then change the value of StudentID, you may not be able to access it again because the hash code will not be the same. Basically, an object should not base its hash code on a mutable property.

Given that, and since you need to override Object.GetHashCode() if you override Object.Equals(), you should also not implement the Object.Equals() or IEquatable<T>.Equals() methods on a mutable object because the object cannot have true value-type semantics without a unique hash code. In this case, where your hash code cannot be based on immutable values, you're better off not implementing the three methods and instead relying on reference-based equality.

If you do need to compare the values between two objects, you're much safer instead implementing the IComparable<T> interface and doing the comparison that way, because IComparable<T> does not require the constraint of overriding Object.GetHashCode().

http://www.imaginaryrealities.com/http://www.imaginaryrealities.com/


April 2. 2010 04:43
When implementing GetHashCode to compare all fields, you may want to look at this: java.sun.com/.../Chapter3.pdf

Granted it was written for Java, but has application in .NET as well.

http://blog.jordanterrell.com/http://blog.jordanterrell.com/


April 2. 2010 14:08
Pingback from topsy.com

Twitter Trackbacks for
        
        J. Michael Palermo IV | All Things Being Equal
        [palermo4.com]
        on Topsy.com

http://topsy.com/trackback?utm_source=pingback&utm_campaign=L1&url=http://palermo4.com/post/All-Things-Being-Equal.aspxhttp://topsy.com/trackback?utm_source=pingback&utm_campaign=L1&url=http://palermo4.com/post/All-Things-Being-Equal.aspx

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading



Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010 J. Michael Palermo IV