If I do the overloading of operator == for a class, I must perform some checks before comparing the fields:
-
if both arguments are null, or both arguments are the same instance, then returns true
Example:
if (System.Object.ReferenceEquals(arg1, arg2)) return true; -
if one is null, but not both, then returns false
Example:
if (((object)arg1 == null) || ((object)arg2 == null)) return false;
Indeed, if I have a struct and I want to do the overloading of operator ==, these checks are not necessary, rather they are useless, for the following reasons: a struct is a value type, so it can not be null, for example DateTime date = null; is not valid, because DateTime (that is a struct) is not a reference type, so you can not compare two DateTime, one of which is set to null.
I created a simple struct Point2D with operator ==, then I compare an instance of Point2D with null:
Point2D point = new Point2D(0,0);
Console.WriteLine((point == null));
-
Obviously the
operator ==it is not called, but the comparison returnsFalse. Which method is called? -
The documentation states that overloading this operator in not-immutable types is not recommended. Why?
Because it seems that the compiler optimizes this away. I tried this code:
And it generated the following IL:
This ultimately boils down to “Create a Point, and then write false to the command line”
This also explains why it doesn’t call your operator. A struct can never be null, and in circumstances where the compiler can guarantee that you are always going to get false as a result, it doesn’t bother issuing code to call an operator at all.
The same thing happens with this code, even though String is a class and overload the == operator:
As for immutability… The == operator in C# is generally interpreted to mean “reference equality”, e.g. these two variables point to the same instance of the class. If you are overloading it, then you generally mean to say that two instances of the class, while not the same instance, should behave as if they were the same instance when their data is the same. The classic example is Strings.
"A" == GiveMeAnA()even though the actual String reference returned byGiveMeAnAmay not be the same as the one represented by the literal"A".If you overloaded the
==operator on classes which were not immutable, then mutation of a class after==had been evaluated could cause numerous subtle bugs.