在相等运算符实现中引用相等运算符

hat*_*ica 5 .net c#

使用Reflector或DotPeek,等于运算符重载的System.Linq.Data.Binary实现如下所示:

[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))));
    }
Run Code Online (Sandbox Code Playgroud)

我必须遗漏一些明显的东西,或者有一种我不知道的机制(例如在体内隐式调用object ==?).我承认,我很少需要重载标准运算符.

为什么这个实现不会导致无限递归(一个简单的测试显示它无法无限递归)?第一个条件表达式是binary1 == binary2,在运算符重载的实现中,如果你在实现之外使用了binary1 == binary2,那么它会被调用,我也会想到.

Cod*_*aos 5

我希望这是你的反编译器中的一个错误.Redgate Reflector有/同样的bug,我也在ILSpy中找到了它.

这很难反编译的原因是因为它巧妙地测试了C#重载规则.原始代码很可能是类似的(object)obj1==(object)obj2,但是这种转换在IL本身中是看不到的.就运行时而言,将任何引用类型转换为基类型都是无操作.但它确实让C#选择引用等式操作码而不是调用重载的相等操作符.

IMO在反编译器中实现这一点的正确方法是始终将参照等式检查反编译(object)obj1==(object)obj2,然后在不影响重载决策的情况下优化冗余转换.这种方法也将解决方法重载的类似问题.