Overloading the Equality Operator in Structure and Classes

If I do operator == overloading for the class, I have to do some checks before comparing the fields:

  • if both arguments are zero, or both arguments are the same instance, then returns true

    Example: if (System.Object.ReferenceEquals(arg1, arg2)) return true;

  • if it is null, but not both, then returns false

    Example: if (((object)arg1 == null) || ((object)arg2 == null)) return false;

Indeed, if I have a structure and I want to perform operator == overloading, these checks are not needed, rather they are useless for the following reasons: struct is a value type, so it cannot be null, for example DateTime date = null; not valid because DateTime (i.e. struct) is not a reference type, so you cannot compare two DateTime , one of which is set to null .

I created a simple Point2D structure with operator == , then compare the Point2D instance with null :

 Point2D point = new Point2D(0,0); Console.WriteLine((point == null)); 
+4
source share
2 answers

Because it seems that the compiler is optimizing this. I tried this code:

 System.Drawing.Point point = new System.Drawing.Point(0,0); Console.WriteLine((point == null)); 

And he generated the following IL:

 IL_0000: ldloca.s 00 IL_0002: ldc.i4.0 IL_0003: ldc.i4.0 IL_0004: call System.Drawing.Point..ctor IL_0009: ldc.i4.0 IL_000A: call System.Console.WriteLine 

It ultimately boils down to "Create a point and then write false to the command line"

It also explains why it does not call your operator. The structure can never be null, and in cases where the compiler can guarantee that you will always get false as a result, it does not bother issuing code to call the operator at all.

The same thing happens with this code, although String is a class and overloads the == operator:

 System.Drawing.Point point = new System.Drawing.Point(0,0); Console.WriteLine("foo" == null); 

Regarding immutability ... The == operator in C # is usually interpreted as "reference equality", for example. these two variables point to the same instance of the class. If you overload it, then you usually say that two instances of a class, and not the same instance, should behave as if they were the same instance when their data is the same. A classic example is Strings. "A" == GiveMeAnA() , although the actual String reference returned by GiveMeAnA may not be the same as that represented by the literal "A" .

If you overloaded the == operator to classes that were not immutable, then the class mutation after == been evaluated, can cause many subtle errors.

+5
source

Chris Shain's answer is correct, but does not explain why this is legal.

When you redefine the equality operator, and both operands are types with zero value, and the return type is bool, then for free we provide you with the removed operator. That is, if you have

 public static bool operator ==(S s1, S s2) { ... } 

then at no additional cost you will receive

 public static bool operator ==(S? s1, S? s2) { ... } 

This is the statement that is being called. Of course, the compiler knows that the result will always be false, because one of the operands is null and the other is never.

There used to be a warning that your code always returns false, but we accidentally disabled it a couple of versions and never returned it back. Tomorrow I am working on this code in the Roslyn compiler, so I will see what I can do to get it back to form.

+12
source

Source: https://habr.com/ru/post/1395337/


All Articles