Labels

Sunday, April 29, 2007

Perfect Equality Choice..

 

There is always a confusion among the Equality choices…

 

Reason:  Looking at System.Object seems surprising at first sight is the fact that it defines four different methods for comparing objects for equality:

 

·         ReferenceEquals() and

·         Two version of Equals().

o   Virtual

o   Static

·         Add to this the comparison operator (==),

 

So, actually we have four ways of comparing for equality.

 

Now what to choose, depends on the mechanism of Object Equality differs depending on whether you are comparing :

·         Reference Types (instances of classes), or

·         Value Types

o   Primitive data types,

o   Instances of structs or enums

 

Before we come to the actual difference let’s have a quick description:

               

1.       ReferenceEquals() Method

a.       Static method

b.      Tests whether two references refer to the same instance of a class.

c.       As a static method, it is not possible to override to compare objects by value. [Drawback – Resolved in 2(a)]

 

2.       Virtual Equals()

a.       Method is virtual, hence can be overridden.

                                                               i.      One point you should note when overriding Equals() is that your override should never throw exceptions.

b.      Throws an exception when overridden and either of the compared object is null. [ Drawback- Resolved in (3(a, b)]

                                                               i.      Definitely the raised exception can be caught, but raising the exception could cause problems for dictionary classes and possibly certain other .NET base classes that internally call this method.[ Drawback- Resolved in (3(a, b)]

c.       Tests whether two references refer to the same instance of a class.

 

3.       Static Equals()

a.       Does the same thing as Virtual with below exceptions

                                                               i.      Takes two parameters

                                                             ii.      This method is able to cope when either of the objects is null, and therefore, provides an extra safeguard against throwing exceptions if there is a risk that an object might be null.

 

b.      Now let say if you need to enjoy the overridden functionality and also want to be sure that nothing should go wrong [i.e no exceptions] when either of the object is null, then here is the solution.

                                                               i.      Use the Static Version and forget it. Here it takes care automatically.

1.       If either of them is null, it will return false, and

2.       If both references actually refer to something, then it calls the virtual instance version of Equals().

a.       This means that when you override the instance version of Equals(), the effect is as if you were overriding the static version as well.

 

 

Now here is the verdict.

 

 

= =

RefererenceEquals(x,y)

Virtual Equals(x)

Static Equals(x,y)

Value Types

Check for Value Equality

Checks for Reference Equality.

 

Will always return false.

Reason: Boxing is required and hence boxing will result into two different objects.

Overridden for ValueTypes: Hence Checks for Value Equality.

 

But, But, But,,,, using ‘==’ for structs [Again a Value Type] willl result in compliation error as there is no overloaded version is present of ‘==’ for value types.

 

Reference Types

Check for Reference Equality & never checks objects based on their contents.

 

Will return False, if both objects are different.

 

Will return True, if both objects are same, i.e points to same location.

Check for Reference Equality & never checks objects based on their contents.

 

Will return False, if both objects are different.

 

Will return True, if both objects are same, i.e points to same location or both are null.

 

 

Problem: Cannot be overridden to compare objects by value.

 

Check for Reference Equality & never checks objects based on their contents.

 

Will return False, if both objects are different.

 

Will return True, if both objects are same or null, i.e points to same location.

 

 

Problem: Can be overridden to compare objects by value, but will throw an exception if either of them is null.

 

Check for Reference Equality & never checks objects based on their contents.

 

Will return False, if both objects are different. Or either if them is null.

 

Will return True, if both objects are same, i.e points to same location or both are null.

 

 

 

String Types

Same as Value Types

Overridden for String Types:  Hence Checks for Value Equality.

 

 

 

Here is the quick walkthrough:

 

 

þ  For comparing Value Types which should be used?

 

o   Object.ReferenceEquals will always return false, at it required boxing value types into reference types. These boxing results in creation of two different objects and hence return false.

 

bool res= Object.ReferenceEquals(1,1);  // False

 

int i=1, j=1;

bool res= Object.ReferenceEquals(i,j); // False

 

So do not use it for Value Types.

 

o   Using ‘==’ or Object.Equals(i, j) or i.Equals(j), for value types will similar results, as both version of Equals() are overloaded by C# to work for value types, and checks content equality.

 

int i=1, j=1;

 

i == j;                                                     // True

                                bool res= i.Equals(j);                        // True

bool res= Object.Equals(i, j);   // True

 

But, But, But,,,, using ‘==’ for structs [Again a Value Type] willl result in compliation error as there is no overloaded version is present of ‘==’ for value types.

 

Using both the version of Equals() for struct will perform perfect and will check the content equality, provided struct do not refer any reference types.

 

þ  For comparing Reference Types which should be used?

 

o   Using ‘==’ :  Will Check reference equality.

 

Class1 obj1=new Class1(1,"AA");

Class1 obj2=new Class1(1,"AA");

 

obj1 == obj2   // False

 

obj1=obj2;

obj1 == obj2   // True

 

 

o   Using Object.ReferenceEquals : Will Check reference equality.

 

Object.ReferenceEquals(obj1,obj2)   // False

 

Obj2=obj1;

Object.ReferenceEquals(obj1,obj2)   // True

 

Obj2=null;

Object.ReferenceEquals(obj1,obj2)   // False

 

o   Using  Someobject.Equals( some obejct): Virtual Version

                                             

obj1.Equals(obj2)   // False

 

Obj2=obj1;

obj1.Equals(obj2)   // True

 

Obj2=null;

obj1.Equals(obj2)   // False or Exception- In case of Overridden. 

 

 

o   Using Object.Equals( some obejct, some obejct): Static Version

 

Object.Equals(obj1,obj2)   // False

 

Obj2=obj1;

Object. Equals (obj1,obj2)   // Will in turn call Virtual method à True

 

Obj2=null;

Object. Equals (obj1,obj2)   // False

 

 

Thanks & Regards,

Arun Manglick

SMTS || Microsoft Technology Practice || Bridgestone - Tyre Link || Persistent Systems || 3023-6258

 

DISCLAIMER ========== This e-mail may contain privileged and confidential information which is the property of Persistent Systems Pvt. Ltd. It is intended only for the use of the individual or entity to which it is addressed. If you are not the intended recipient, you are not authorized to read, retain, copy, print, distribute or use this message. If you have received this communication in error, please notify the sender and delete all copies of this message. Persistent Systems Pvt. Ltd. does not accept any liability for virus infected mails.

No comments:

Post a Comment