派生类的通用等式实现

时间:2018-04-28 07:18:36

标签: c# generics equality

我希望派生某些类A的对象也能以某种方式推导出Equals(A other)的实现,它将执行以下操作:如果thisother的类型不同,返回false,否则返回this.value == other.value

我的尝试看起来像这样:

public class A<T> : IEquatable<A<T>>
    where T: A<T>
{
    protected string Value { get; }
    public A(string value)
    {
        Value = value;
    }

    public bool Equals(A<T> other)
    {
        var concrete = other as T;
        if (concrete == null)
        {
            return false;
        }

        return concrete.Value == Value;
    }
}

public class B : A<B>
{
    public B(string value)
        : base(value)
    {

    }
}

public class C : A<C>
{
    public C(string value)
        : base(value)
    {

    }
}

class Program
{
    static void Main(string[] args)
    {
        var b1 = new B("val");
        var b2 = new B("val");
        var c = new C("val");

        Console.WriteLine(b1.Equals(b1));
        Console.WriteLine(b1.Equals(b2));
        Console.WriteLine(b2.Equals(b1));
        Console.WriteLine(b1.Equals(c));
        Console.WriteLine(b2.Equals(c));
        Console.WriteLine(c.Equals(b1));
        Console.WriteLine(c.Equals(b2));
    }
}

这样可以正常工作,直到我们得到更多:

public class D : C
{
    public D(string value)
        : base(value)
    {

    }
}
然后它破了:

        var d = new D("val");
        Console.WriteLine(d.Equals(c)); // prints "True"

现在我被卡住了。我如何使其工作? 修复实现以使用多个继承级别并防止多个级别的继承都是可以接受的。

我理解虽然我必须将A<T>的所有第一级后代声明为密封,但这是最后的手段,除非它可以某种方式强制执行(因此A<T>的非密封后代会导致编译错误)。 或者我的方法可能完全错了?

1 个答案:

答案 0 :(得分:2)

这都是因为as运算符可以毫无问题地将子类转换为超类。

您要做的是检查类型并确定它们是否相同:

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

getting-startedGetTypetypeofis的行为有关,其行为与as类似。