繁体   English   中英

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

[英]Referencing equality operator within equality operator implementation

使用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))));
    }

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

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

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

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

IMO在反编译器中实现它的正确方法是始终将引用相等性检查反编译为(object)obj1==(object)obj2 ,然后在不影响重载(object)obj1==(object)obj2优化冗余转换。 这种方法也将解决方法重载的类似问题。

这显然是你的ReSharper(和dotpeek)版本中的一个错误。 ReSharper版本6.0(6.0.2202.688)正确执行:

    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);
    } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM