Theres many ways to test equality between two object in fact theres four we have Object.ReferenceEquals(), static Equals(), instance Equals(), operator==
Object.ReferenceEquals();
This method simple test the equality of referances of two referance types so if these two types are pointing to the same referance so they forsure pointing to the same type with same content, however if you tried to compare between two value types you will get false always even if compare one type to it self like line 4 in the following code.
1 2 3 4 5 6 |
int n1 = 10; int n2 = 10;
Object.ReferenceEquals( n1,n2 ); //always return false
Object.ReferenceEquals( n1,n1 ); //always return false |
static Equals()
This one is tough this static method is inhirted from the base class Object simply calling Equals() delegate to the implementation of one of the types being compared.
this is how Equals() could be implemented
1 2 3 4 5 6 7 8 9 10 |
public static bool Equals( object left, object right ) { // Check object identity if (left == right ) return true; // both null references handled above if ((left == null) || (right == null)) return false; return left.Equals (right); } |
where the actual responsibility is delegated to left object. remember that you can't override this function.
instance Equals()
Now what if you created a value type for example and you want to defind your own custom way to test equality this is when you shoud do some actual coding.. overide the instance method Equals() remember that you don't have to implement your own version of Equals() unless the default implementation don't match your desire or not work best for your created value type.
This example show how you may implement your own Equals()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
ublic class Foo { public override bool Equals( object right ) { if (right == null) return false;
if (object.ReferenceEquals( this, right )) return true;
if (this.GetType() != right.GetType()) return false;
return CompareFooMembers( this, right as Foo ); } } |
In the first check (line 5) we check if the object has value, the second comparison we try to match the two object referances (line 7) and last comparison in (line 11) we compare the Foo members (content) ...anyway so what about the (line 9).
One of the properties of equality is symmetric but this is not the case here. in the coming peace of code we will compare two types Base type and Derived type and see how symmetrically is an issue here.
Class B - The base class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class B { public override bool Equals( object right ) { // check null: if (right == null) return false;
// Check reference equality: if (object.ReferenceEquals( this, right )) return true;
// Problems here, discussed below. B rightAsB = right as B; if (rightAsB == null) return false;
return CompareBMembers( this, rightAsB ); } } |
Class D - The drived class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class D : B { // etc. public override bool Equals( object right ) { // check null: if (right == null) return false;
if (object.ReferenceEquals( this, right )) return true;
// Problems here. D rightAsD = right as D; if (rightAsD == null) return false;
if (base.Equals( rightAsD ) == false) return false;
return CompareDMembers( this, rightAsD ); }
} |
Test Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
B baseObject = new B(); D derivedObject = new D();
// Comparison 1. if (baseObject.Equals(derivedObject)) Console.WriteLine( "Equals" ); else Console.WriteLine( "Not Equal" );
// Comparison 2. if (derivedObject.Equals(baseObject)) Console.WriteLine( "Equals" ); else Console.WriteLine( "Not Equal" ); |
In the comparison one the condition will evalueate to true as the derived type can be converted implicty to the base type so it passes this condition at the implementation of the Equals() like
if (this.GetType() != right.GetType()) return false;
however this is not vice versa as the base type can't be casted to the derived.
operator==
This is very similar to instance Equals() you may have to overrid this operator to match the logic of equality behid your custom created value type.
but remember that any modification of operator== or instance Equals() may affect other equality function.
More information on testing equality