运算符重载==,!=,等于

Sag*_*ari 49 .net c# compiler-errors operator-overloading

我已经经历了一个问题

我明白,有必要实施==,!=Equals().

public class BOX
{
    double height, length, breadth;

    // this is first one '=='
    public static bool operator== (BOX obj1, BOX obj2)
    {
        return (obj1.length == obj2.length 
                    && obj1.breadth == obj2.breadth 
                    && obj1.height == obj2.height);
    }

    // this is second one '!='
    public static bool operator!= (BOX obj1, BOX obj2)
    {
        return !(obj1.length == obj2.length 
                    && obj1.breadth == obj2.breadth 
                    && obj1.height == obj2.height);
    }

    // this is third one 'Equals'
    public override bool Equals(BOX obj)
    {
        return (length == obj.length 
                    && breadth == obj.breadth 
                    && height == obj.height);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想,我已经写代码适当覆盖==,!=,Equals运营商.虽然,我得到编译错误如下.

'myNameSpace.BOX.Equals(myNameSpace.BOX)' is marked as an override 
but no suitable method found to override.
Run Code Online (Sandbox Code Playgroud)

所以,问题是 - 如何覆盖上面的运算符并摆脱这个错误?

Yuv*_*kov 54

正如Selman22所说,你要覆盖默认object.Equals方法,它接受一个object obj非安全的编译时类型.

为了实现这一点,请制作您的类型工具IEquatable<Box>:

public class Box : IEquatable<Box>
{
    double height, length, breadth;

    public static bool operator ==(Box obj1, Box obj2)
    {
        if (ReferenceEquals(obj1, obj2))
        {
            return true;
        }

        if (ReferenceEquals(obj1, null))
        {
            return false;
        }
        if (ReferenceEquals(obj2, null))
        {
            return false;
        }

        return (obj1.length == obj2.length
                && obj1.breadth == obj2.breadth
                && obj1.height == obj2.height);
    }

    // this is second one '!='
    public static bool operator !=(Box obj1, Box obj2)
    {
        return !(obj1 == obj2);
    }

    public bool Equals(Box other)
    {
        if (ReferenceEquals(null, other))
        {
            return false;
        }
        if (ReferenceEquals(this, other))
        {
            return true;
        }

        return height.Equals(other.height) 
               && length.Equals(other.length) 
               && breadth.Equals(other.breadth);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }
        if (ReferenceEquals(this, obj))
        {
            return true;
        }

        return obj.GetType() == GetType() && Equals((Box)obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hashCode = height.GetHashCode();
            hashCode = (hashCode * 397) ^ length.GetHashCode();
            hashCode = (hashCode * 397) ^ breadth.GetHashCode();
            return hashCode;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另外需要注意的是,您使用等于运算符进行浮点比较,您可能会遇到精度损失.


Sel*_*enç 33

我想你宣布这样的Equals方法:

public override bool Equals(BOX obj)
Run Code Online (Sandbox Code Playgroud)

由于该object.Equals方法采用对象,因此没有方法可以使用此签名覆盖.你必须像这样覆盖它:

public override bool Equals(object obj)
Run Code Online (Sandbox Code Playgroud)

如果你想要类型安全,Equals,你可以实现IEquatable<BOX>.


epo*_*pox 22

实际上,这是一个"如何"的主题.那么,这是参考实现:

    public class BOX
    {
        double height, length, breadth;

        public static bool operator == (BOX b1, BOX b2)
        {
            if ((object)b1 == null)
                return (object)b2 == null;

            return b1.Equals(b2);
        }

        public static bool operator != (BOX b1, BOX b2)
        {
            return !(b1 == b2);
        }

        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;

            var b2 = (BOX)obj;
            return (length == b2.length && breadth == b2.breadth && height == b2.height);
        }

        public override int GetHashCode()
        {
            return height.GetHashCode() ^ length.GetHashCode() ^ breadth.GetHashCode();
        }
    }
Run Code Online (Sandbox Code Playgroud)

参考:https://msdn.microsoft.com/en-us/library/336aedhh(v = vs.100).aspx #Examples

  • 不要写`if(null == b1)`,它会重新执行`operator ==`重载,导致stackoverflow.同样适用于`b2`. (17认同)
  • @grek40,“if ((object)b1==null)”会避免这个问题吗? (2认同)
  • 是的,这应该可以解决问题.替代方案是使用`object.ReferenceEquals`,就像其他答案一样. (2认同)
  • 对于HashCode的生成,最好使用tupple.GetHashCode():`(高度,长度,宽度).GetHashCode()。使用XOR的问题是高度,长度,宽度可能仅使用低位,而未使用高位。哈希最好使用整数的所有32位。这是通过将参数按不同的值进行位移位来实现的,GetHashCode()可以这样做。 (2认同)

小智 8

public class BOX
{
    double height, length, breadth;

    public static bool operator == (BOX b1, BOX b2)
    {
        if (b1 is null)
            return b2 is null;

        return b1.Equals(b2);
    }

    public static bool operator != (BOX b1, BOX b2)
    {
        return !(b1 == b2);
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        return obj is BOX b2? (length == b2.length && 
                               breadth == b2.breadth && 
                               height == b2.height): false;

    }

    public override int GetHashCode()
    {
        return (height,length,breadth).GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)