I want to know the best way to compare two objects and to find out if they\'re equal. I\'m overriding both GethashCode and Equals. So a basic class looks like:
Your current equality method is broken - there are more values than possible hash codes. It's entirely reasonable (and expected) that you will occasionally have values which are unequal but give the same hash. Equals should check the actual values:
public override bool Equals(object obj)
{
Test test = obj as Test;
if (obj == null)
{
return false;
}
return Value == test.Value &&
String1 == test.String1 &&
String2 == test.String2;
}
A few things to note:
Your way of generating the hashcode will give the same value for any fixed Value
if String1
and String2
are the same; it will also blow up if String1
or String2
is null. This is an unfortunate aspect of using XOR for hashing. I prefer something like this:
// Put this extension method in a utility class somewhere
public static int SafeGetHashCode<T>(this T value) where T : class
{
return value == null ? 0 : value.GetHashCode();
}
// and this in your actual class
public override int GetHashCode()
{
int hash = 19;
hash = hash * 31 + Value;
hash = hash * 31 + String1.SafeGetHashCode();
hash = hash * 31 + String2.SafeGetHashCode();
return hash;
}
Generally speaking, equality becomes tricky when inheritance gets involved. You may want to consider sealing your class.
You may also want to implement IEquatable<Test>
wouldn't a function Equals always test only against the same type, shouldn't it be:
//override
public bool Equals(Test other)//(object obj)
{
//return GetHashCode() == obj.GetHashCode();
return (Value == other.Value) &&
(String1 == other.String1) &&
(String2 == other.String2);
}
regards Oops
simple
Object.Equals(obj1, obj2);
Your Equals
is incorrect - that should define what it means for two things to be equal - and having the same hash-code does not mean equality (however; a different hash-code does mean non-equality). If "equality" means "both strings are pairwise equal", then test that.
Re a better hash; xor is notorious for this, since it is trivial to get 0 by xor a value with itself. A better approach may be something like:
int i = 0x65407627;
i = (i * -1521134295) + Value.GetHashCode();
i = (i * -1521134295) + (String1 == null ? 0 : String1.GetHashCode());
i = (i * -1521134295) + (String2 == null ? 0 : String2.GetHashCode());
return i;
For any two objects, object equality implies hash code equality, however, hash code equality does not imply object equality. From Object.GetHashCode on MSDN:
A hash function must have the following properties:
If two objects compare as equal, the GetHashCode method for each object must return the same value. However, if two objects do not compare as equal, the GetHashCode methods for the two object do not have to return different values.
In other words, your Equals
is written wrong. It should be something like:
public override bool Equals(object obj)
{
Test other = obj as Test;
if (other == null)
return false;
return (Value == other.Value)
&& (String1 == other.String1)
&& (String2 == other.String2);
}
GetHashCode
is good for collections (like Dictionary<K, V>
) to quickly determine approximate equality. Equals
is for comparing if two objects really are the same.
You could serialise the two objects to JSON, then compare the two strings to see if they are the same.
For example
JavaSriptSerializer serialiser = new JavaScriptSerializer();
string t1String = serialiser.Serialize(t);
string t2String = serialiser.Serialize(t2);
if(t1String == t2String)
return true; //they are equal
else
return false;