Я пишу программу, которая пишет С#, которая в конечном итоге скомпилируется в приложение. Я хотел бы, чтобы каждый из сгенерированных типов предоставлял функцию "глубокого клонирования", которая копирует все дерево данных. То есть, я хочу, чтобы кто-то мог:
var x = new Base(); // Base has public virtual Base DeepClone() { ... }
var y = new Derived(); // Derived overrides DeepClone
Base a = x.DeepClone();
Base b = y.DeepClone();
// Derived c = x.DeepClone(); // Should not compile
Derived d = y.DeepClone(); // Does not compile, DeepClone returns Base
вместо
var x = new Base();
var y = new Derived();
Base a = x.DeepClone();
Base b = y.DeepClone();
// Derived c = x.DeepClone(); // Should not compile
Derived d = (Derived)y.DeepClone();
Однако С# не позволяет вам сделать это в простой переопределении; переопределения должны возвращать тот же тип, что и объявленный тип на базе.
Так как я пишу код, который все равно печатает шаблон, есть ли что-то, что я могу создать, чтобы первый блок мог компилироваться? Я попробовал что-то похожее на следующее:
abstract class Base
{
public abstract Base DeepClone();
}
class Base2 : Base
{
int Member { get; set; }
public Base2() { /* empty on purpose */ }
public Base2(Base2 other)
{
this.Member = other.Member;
}
public override Base2 DeepClone()
{
return new Base2(this);
}
}
sealed class Derived : Base2
{
string Member2 { get; set; }
public Derived() { /* empty on purpose */ }
public Derived(Derived other)
: base(other)
{
this.Member2 = other.Member2;
}
public override Derived DeepClone()
{
return new Derived(this);
}
}
но это не компилируется, потому что переопределения не совпадают. Я также попытался переопределить метод из базы и скрыть его "новым" ключевым словом, но это тоже не сработало.