Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding the == operator in non-immutable types

The MSDN Guidelines for Overloading Equals() and Operator == state:

By default, the operator == tests for reference equality by determining if two references indicate the same object, so reference types do not need to implement operator == in order to gain this functionality. When a type is immutable, meaning the data contained in the instance cannot be changed, overloading operator == to compare value equality instead of reference equality can be useful because, as immutable objects, they can be considered the same as long as they have the same value. Overriding operator == in non-immutable types is not recommended.

Can anyone explain the reasoning behind the bold?

EDIT - Also, is this guideline relevant to the == operator only, or is it meant for the Equals method as well ?

like image 702
Ohad Schneider Avatar asked Dec 28 '10 14:12

Ohad Schneider


1 Answers

My educated guess would be to make things operate like the built in types in .NET do, namely that == should work like reference equality where possible, and that Equals should work like value equality where possible. Consider the actual difference between == and Equals:

object myObj = new Integer(4);
object myObj2 = new Integer(4);

//Note that == is only called if the ref'd objects are cast as a type
//overloading it.
myObj == myObj2; //False (???)
myObj.Equals(myObj2); //True (This call is virtual)

//Set the references equal to each other -- note that the operator==
//comparison now works.
myObj2 = myObj;
myObj == myObj2; //True
myObj.Equals(myObj2); //True

This behavior is of course inconsistent and confusing, particularly to new programmers -- but it demonstrates the difference between reference comparisons and value comparisons.

If you follow this MSDN guideline, you are following the guideline taken by important classes such as string. Basically -- if a comparison using == succeeds, the programmer knows that that comparison will always succeed, so long as the references involved don't get assigned to new objects. The programmer need never worry about the contents of the objects being different, because they never will be different:

//Mutable type
var mutable1 = new Mutable(1);
var mutable2 = mutable1;
mutable1 == mutable2; //true
mutable1.MutateToSomethingElse(56);
mutable1 == mutable2; //still true, even after modification
//This is consistent with the framework. (Because the references are the same,
//reference and value equality are the same.) Consider if == were overloaded,
//and there was a difference between reference and value equality:

var mutable1 = new Mutable(1);
var mutable2 = new Mutable(1);
mutable1 == mutable2; //true
mutable1.MutateToSomethingElse(56);
mutable1 == mutable2; //oops -- not true anymore
//This is inconsistent with, say, "string", because it cannot mutate.

It boils down to that there's no real technical reason for the guideline -- it's just to remain consistent with the rest of the classes in the framework.

like image 170
Billy ONeal Avatar answered Oct 10 '22 21:10

Billy ONeal