2

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

类中的 Equals 实现Coordinate

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

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

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

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

4

2 回答 2

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);
    }
}
于 2014-03-15T14:42:35.213 回答
1

当你说obj1.Equals(obj2), obj2is of type ValueObject<T>which 不匹配Tin public abstract bool Equals(T obj)

事实上,在运行时,它可能与T.

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

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

我认为你 indendT等于ValueObject<T>. 你可以说where T : ValueObject<T>。这至少在类型系统中编码了您想要的部分内容并为您节省了(object)演员表。

于 2014-03-15T14:22:41.350 回答