抽象类实现相等运算符

时间:2018-12-13 02:35:24

标签: c#

可以说我定义了以下抽象类:

public abstract class ValueEquality<T> : IEquatable<T> 
    where T : ValueEquality<T>
{
    public override bool Equals(object obj)
    {
        return Equals(obj as T);
    }

    public static bool operator ==(ValueEquality<T> lhs, object rhs)
    {
        if (ReferenceEquals(lhs, rhs))
        { 
            return true;
        }
        else if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
        {
            return false;
        }
        else
        {
            return lhs.Equals(rhs);
        }
    }

    public static bool operator !=(ValueEquality<T> lhs, object rhs)
    {
        return !(lhs == rhs);
    }

    public bool Equals(T other)
    {
        return other != null && EqualNoNull(other);
    }

    public abstract override int GetHashCode();

    public abstract bool EqualNoNull(T other);
}

然后如下创建类C

public class C : MyEquatable<C>
{
    public override bool EqualsNoNull(C other)
    {
        ...
    }

    public override int GetHashCode()
    {
        ...
    }
}

如果我有代码,

C x1;
C x2;
bool equal = x1 == x2;

最终会在C中调用equals方法吗?这种方法有什么陷阱吗?

编辑:修复了答案引起的代码中的一些问题。

2 个答案:

答案 0 :(得分:2)

此代码将在以下位置进行无限循环

public override bool Equals(object obj)
{
    try
    {
        T otherT = (T) obj;
        return Equals(this, otherT);
    }
    catch (InvalidCastException)
    {
        return false;
    }
}

它将一次又一次调用Equals(object obj)。正确的实施方式:

public abstract class MyEquatable<T> : IEquatable<T>
    where T : MyEquatable<T>
{
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }

        if (ReferenceEquals(this, obj))
        {
            return true;
        }

        if (obj.GetType() != this.GetType())
        {
            return false;
        }

        return this.Equals((MyEquatable<T>)obj);
    }

    protected bool Equals(MyEquatable<T> other)
    {
        return this.Equals(other as T);
    }


    public static bool operator ==(MyEquatable<T> lhs, object rhs)
    {
        return Equals(lhs, rhs);
    }

    public static bool operator !=(MyEquatable<T> lhs, object rhs)
    {
        return Equals(lhs, rhs);
    }

    public abstract bool Equals(T other);
    public abstract override int GetHashCode();
}

x1 == x2将调用==中的运算符MyEquatable,它将调用Equals(object obj)。最后,它调用Equals(T other)类中覆盖的C

答案 1 :(得分:0)

遵循文档中通常建议的另一种实现方式

public abstract class MyEquatable<T> : IEquatable<T>
    where T : MyEquatable<T> {

    public override bool Equals(object obj) {

        if (ReferenceEquals(obj, null) || obj.GetType() != GetType())
            return false;

        var valueObject = obj as T; //Note the cast

        if (ReferenceEquals(valueObject, null))
            return false;

        return Equals(valueObject); //Calls Equals(T other)
    }

    public abstract bool Equals(T other);
    public abstract override int GetHashCode();

    public static bool operator ==(MyEquatable<T> left, MyEquatable<T> right) {
        if (ReferenceEquals(left, null) && ReferenceEquals(right, null))
            return true;

        if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
            return false;

        return left.Equals(right);
    }

    public static bool operator !=(MyEquatable<T> left, MyEquatable<T> right) {
        return !(left == right);
    }
}