Okay, so if I override Equals, I need to override GetHashCode and vice versa.
But I just wonder: Should I always override these two in any class? Especially if I kno
Only if you want Value semantics. From MSDN:
For some kinds of objects, it is desirable to have Equals test for value equality instead of referential equality. Such implementations of Equals return true if the two objects have the same value, even if they are not the same instance. The definition of what constitutes an object's value is up to the implementer of the type, but it is typically some or all of the data stored in the instance variables of the object. For example, the value of a string is based on the characters of the string; the Equals method of the String class returns true for any two instances of a string that contain exactly the same characters in the same order.
As far as I'm aware you only need to override them if you need value equality semantics. The System.Object implementation isn't 'bad', it just only does a reference check (which is all an implementation at that level can do).
In short: If you need some sort of value based equality (equality based on properties of the class), then yes, override away. Otherwise, it should be more than fine already.
EDIT:
You only need to override them in the case above. If you override one, you do need to override both for the obvious reasons (they need to be consistent, etc). You can override them on every class for other reasons noted in other answers (like performance in algorithms that use the hash value, ie. Dictionary
keys, etc), but you don't need to, the default System.Object
implementation will work correctly.
EDIT 2: More information requested, so here goes. Consider the following pseudo-class:
public class User {
private int _id;
private string _username;
public string Username { get {return _username;}};
// [snip] Whatever other properties we might like to have.
public User(string username) {
// Initialise our user from a database, or whatever.
}
}
As it stands, the following code, might seem intuitive:
User foo = new User("me");
User bar = new User("me");
User baz = foo;
if (foo.Equals(bar)) {
Console.WriteLine("1: Success!");
}
if (foo.Equals(baz)) {
Console.WriteLine("2: Success!");
}
But it will only print out:
2: Success
Why? foo
and bar
are two seperate instances of the class, and have separate references. A reference is like a pointer in C/C++. foo and baz are the same reference because one was assigned from the other. They all have the same value though, the user called "me". A sample implementation of a value based .Equals
implementation might be:
partial class User {
public override bool Equals(object b) {
if (b == null) return false;
if (b.GetType() != this.GetType()) return false;
// Now the heavy lifting
User other = (User)b;
if (other._id == this._id) return true;
else return false;
}
}
See how it checks against part of the class's properties to determine equality? That's value equality at work. Reference equality would just be a simple this == b
check.
The two methods should be consistent. In other words, if two objects are equal, then each should return the same hash code. This is particularly important in hashed collections. To find an object that matches object X in a hashed container, the container will only test those items for equality that have the same hash code as X.