【发布时间】:2026-02-04 06:25:01
【问题描述】:
我正在编写一个编写 C# 的程序,该程序最终会编译到应用程序中。我希望每个生成的类型都提供一个“深度克隆”功能来复制整个数据树。也就是说,我希望有人能够做到:
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();
但是,C# 不允许您在简单的覆盖中执行此操作;覆盖必须返回与基上声明的类型相同的类型。
由于我编写的代码无论如何都会消除样板,所以我可以生成一些东西来允许第一个块编译吗?我尝试了类似以下的方法:
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);
}
}
但这不会编译,因为覆盖不匹配。我还尝试从基础中覆盖该方法并使用“new”关键字将其隐藏,但这也不起作用。
【问题讨论】:
-
不幸的是,在 C# 中,一个类无法泛指其自己的类型。有一些 hacky 方法,比如奇怪地重复出现的模板模式,它可以为您节省样板工作,但并非万无一失。
-
@Asad:这里不涉及泛型。
-
"这里没有涉及泛型" 是的,但是这个问题在概念上是泛型之一。你想要一个
DeepClone方法,它可以接受从Base派生的任意类型,对其执行一些操作,并返回相同的类型。 -
@Asad:不,我希望
DeepClone成为非通用成员。 -
@Scott:不幸的是,这与需要类而不是接口的序列化程序一起使用。 (如果它是一个接口,我可以明确地实现它)
标签: c# clone covariance contravariance