I have read that when you override Equals on an class/object you need to override GetHashCode.
public class Person : IEquatable<Person>
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(int personId, string firstName, string lastName)
{
PersonId = personId;
FirstName = firstName;
LastName = lastName;
}
public bool Equals(Person obj)
{
Person p = obj as Person;
if (ReferenceEquals(null, p))
return false;
if (ReferenceEquals(this, p))
return true;
return Equals(p.FirstName, FirstName) &&
Equals(p.LastName, LastName);
}
}
Now given the following:
public static Dictionary<Person, Person> ObjDic= new Dictionary<Person, Person>();
public static Dictionary<int, Person> PKDic = new Dictionary<int, Person>();
Will not overridding the GetHashCode affect both of the Dictionary's above? What I am basically asking is how is GetHashCode generated? IF I still look for an object in PKDic will I be able to find it just based of the PK. If I wanted to override the GetHashCode how would one go about doing that?
You should always override GetHashCode
.
A Dictionary<int, Person>
will function without GetHashCode
, but as soon as you call LINQ methods like Distinct
or GroupBy
, it will stop working.
Note, by the way, that you haven't actually overridden Equals
either.
The IEquatable.Equals
method is not the same as the virtual bool Equals(object obj)
inherited from Object
. Although the default IEqualityComparer<T>
will use the IEquatable<T>
interface if the class implements it, you should still override Equals
, because other code might not.
In your case, you should override Equals
and GetHashCode
like this:
public override bool Equals(object obj) { return Equals(obj as Person); }
public override int GetHashCode() {
return FirstName.GetHashCode() ^ LastName.GetHashCode();
}
In your scenario, not overriding GetHashCode
on your type will affect only the first dictionary, as the key is what's used for hashing, not the value.
When looking for the presence of a key, the Dictionary<TKey,TValue>
will use the hash code to find out if any keys could be equal. It's important to note that a hash is a value that can determine if two things could be equal or very likely are equal. A hash, strictly speaking cannot determine if two items are equal.
Two equal objects are required to return the same hash code. However, two non-equal objects are not required to return different hash codes. In other words, if the hash codes don't match, you're guaranteed that the objects are not equal. If the hash codes do match, then the objects could be equal.
Because of this, the Dictionary
will only call Equals
on two objects if their hash codes match.
As to "how to override GetHashCode
", that's a complicated question. Clasically, a hashing algorithm should provide a balance between even distribution of the codes over the set of values with a low collision rate (a collision is when two non-equal objects produce the same code). This is a simple thing to describe and a very difficult thing to accomplish. It's easy to do one or the other, but hard to balance them.
From a practical perspective (meaning disregarding performance), you could just XOR
all of the characters of the first and last names (or even use their respective hash codes, as Joel suggests) as your hash code. This will give a low degree of collision, but won't result in a terribly even distribution. Unless you're dealing with very large sets or very frequent lookups, it won't be an issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With