5

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.

2 Answers2

5

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.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
2

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);
    } 
Corey Kosak
  • 2,615
  • 17
  • 13