Я хочу, чтобы объекты, порождающие определенный класс A
, также каким-то образом извлекали реализацию Equals(A other)
, которая выполняла бы следующее: если типы this
и other
различны, возвращают 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>
вызовут ошибку компиляции).
Или, может быть, мой подход совершенно неверен?