Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Referencing equality operator within equality operator implementation

Tags:

c#

.net

Using Reflector or DotPeek, the System.Linq.Data.Binary implementation of the equality operator overload looks like this:

[Serializable, DataContract]
public sealed class Binary : IEquatable<Binary>
{
...
    public static bool operator ==(Binary binary1, Binary binary2)
    {
        return ((binary1 == binary2) || (((binary1 == null) && (binary2 == null)) || (((binary1 != null) && (binary2 != null)) && binary1.EqualsTo(binary2))));
    }

I must be missing something obvious, or there is a mechanism taking place of which I'm unaware (such as implicitly calling object == within the body?). I admit, I rarely if ever need to overload standard operators.

Why does this implementation not result in an infinite recursion (which a simple test shows it doesn't recurse infinitely)? The first conditional expression is binary1 == binary2, within the implementation of the operator overload that would get called if you used binary1 == binary2 outside the implementation, and I would have thought, inside as well.

like image 276
hatchet - done with SOverflow Avatar asked Aug 07 '11 17:08

hatchet - done with SOverflow


People also ask

How does the == operator check for equality?

The equal-to operator ( == ) returns true if both operands have the same value; otherwise, it returns false . The not-equal-to operator ( != ) returns true if the operands don't have the same value; otherwise, it returns false .

What is correct regarding == and === operators?

= is used for assigning values to a variable, == is used for comparing two variables, but it ignores the datatype of variable whereas === is used for comparing two variables, but this operator also checks datatype and compares two values.

Is it safe to use the equality operators to compare reference types?

Most reference types must not overload the equality operator, even if they override Equals. However, if you are implementing a reference type that is intended to have value semantics, such as a complex number type, you must override the equality operator.

What is == and === in Javascript?

The main difference between the == and === operator in javascript is that the == operator does the type conversion of the operands before comparison, whereas the === operator compares the values as well as the data types of the operands.


2 Answers

I expect this to be a bug in your decompiler. Redgate Reflector had/has the same bug, and I've found it in ILSpy too.

The reason why this is hard to decompile is because it subtly tests the C# overloading rules. The original code was most likely something like (object)obj1==(object)obj2, but this conversion can't be seen in the IL itself. Casting any reference type to a base type is a no-op as far as the runtime is concerned. It does however get C# to choose the referential equality opcodes instead of calling the overloaded equality operators.

IMO the correct way to implement this in a decompiler is to always decompile referential equality checks to (object)obj1==(object)obj2 and then optimize out the redundant casts if they don't affect overload resolution. This approach will fix similar problems with method overloading too.

like image 83
CodesInChaos Avatar answered Oct 03 '22 06:10

CodesInChaos


It is evidently a bug in your version of ReSharper (and dotpeek). Version 6.0 (6.0.2202.688) of ReSharper does it correctly:

    public static bool operator ==(Binary binary1, Binary binary2) {
        if ((object)binary1 == (object)binary2) 
            return true; 
        if ((object)binary1 == null && (object)binary2 == null)
            return true; 
        if ((object)binary1 == null || (object)binary2 == null)
            return false;
        return binary1.EqualsTo(binary2);
    } 
like image 43
Corey Kosak Avatar answered Oct 03 '22 08:10

Corey Kosak