IEquatable实现和运算符覆盖

时间:2014-03-15 14:05:16

标签: c# .net inheritance abstract-class iequatable

域类T的类型可以是ValueObject<T>

public class Coordinate: ValueObject<Coordinate>
{ ... }

ValueObject<T>实现IEquatable接口。我希望ValueObject<T>的每个具体实现为bool Equals(T obj)提供实现,因此我将其创建为抽象方法:

public abstract class ValueObject<T> : IEquatable<T>
{
    public abstract bool Equals(T obj);

    public static bool operator ==(ValueObject<T> obj1, ValueObject<T> obj2)
    {
        if (object.ReferenceEquals(obj1, obj2)) return true;
        if (object.ReferenceEquals(obj1, null)) return false;
        if (object.ReferenceEquals(obj2, null)) return false;

        return obj1.Equals(obj2);
    }
}

Coordinate类中的Equals实现:

public class Coordinate : ValueObject<Coordinate>
{
    // ...

    public override bool Equals(Coordinate other)
    {
        return (other != null) && (this.Latitude == other.Latitude) && (this.Longitude == other.Longitude);
    }
}

ValueObject<T>为==(和for = =,上面未显示)提供了通用操作覆盖,适用于所有具体实现。

问题是,当从==覆盖调用Equals方法时,它会调用Object.Equals()而不是Coordinate.Equals()

2 个答案:

答案 0 :(得分:6)

  

问题是,当从Equals覆盖调用==方法时,它会调用Object.Equals()而不是Coordinate.Equals()

不,问题是那些东西是不同的。如果它们是相同的,那么它就没有问题了。

所以让他们一样。不要让派生阶级做错事; 强迫他们做正确的事

public abstract class ValueObject<T> : IEquatable<T>
{
    // Force the derived class to override these.
    public abstract override bool Equals(object obj);
    public abstract override int GetHashcode(object obj);

    // And then consistently use the overridden method as the implementation.
    public virtual bool Equals(T obj)
    {
        return obj1.Equals((object)obj2);
    }
    public static bool operator ==(ValueObject<T> obj1, ValueObject<T> obj2)
    {
         return obj1.Equals((object)obj2);
    }
    public static bool operator !=(ValueObject<T> obj1, ValueObject<T> obj2)
    {
         return !obj1.Equals((object)obj2);
    }
}

答案 1 :(得分:1)

当您说obj1.Equals(obj2)时,obj2的{​​{1}}类型与ValueObject<T>中的T不符。

实际上,在运行时它可能与public abstract bool Equals(T obj)不同。

在这种情况下,你可能想要返回false。

T

我认为你认为public static bool operator ==(ValueObject<T> obj1, ValueObject<T> obj2) { if (object.ReferenceEquals(obj1, obj2)) return true; if (object.ReferenceEquals(obj1, null)) return false; if (object.ReferenceEquals(obj2, null)) return false; if (obj1.GetType() != obj2.GetType()) return false; //new return ((T)(object)obj1).Equals((T)(object)obj2); } 等于T的派生类。你可以说ValueObject<T>。这至少会编码您在类型系统中所需的部分内容,并为您节省where T : ValueObject<T>演员阵容。