实现一个通用方法

4
我创建了一个接口,其中只有一个方法,即将一个对象的内容复制到同类型的另一个对象中(实际功能与问题无关)。
public interface IDeepClonable
{
    void DeepClone<T>(T other);
}

我在正确实现方面遇到了麻烦。

我真正想要的是像这样实现它(其中此代码位于实现IDeepClonable的ClassA类内部)

public void DeepClone<ClassA>(ClassA other)
{
    this.A = other.A;
}

然而,这并不起作用,因为“other”对象未被编译器识别为ClassA的实例(为什么?)
这也不起作用,因为它会显示“类型参数T的约束条件必须与(...)接口方法匹配。”
public void DeepClone<T>(T other) where T : ClassA
{
    this.A= other.A;
}

我可以通过修改接口,将其接受一个对象而不是通用约束来解决所有问题,但我希望有一个更加优雅的解决方案。

我也可以通过将接口转换为通用接口来解决此问题,但这会强制我进行通用接口的强制类型转换。


1
顺带一提,DeepClone 不是正确的名称;一个名为 DeepClone 的方法应该返回一个副本。你应该将其命名为 DeepCloneFrom 或类似名称。 - SLaks
我建议,如果你要进行大量的深度克隆,最好定义IImmutableClonable<T>接口,并带有方法T AsImmutable()IModifiableClone<U>接口并带有方法U AsNewMutable(),以及继承上述两个接口的IFullClone<T,U>接口。不可变对象将从其AsImmutable()实现中简单地返回自身;AsNewMutable()将返回至少允许U合同所需的任何突变方法的东西。 - supercat
2个回答

5

你正在尝试使用CRTP

你需要编写

public interface IDeepClonable<out T> where T : IDeepClonable<T>
{
    void DeepClone(T other);
}

public class ClassA : IDeepClonable<ClassA> {
    void DeepClone(ClassA other) { ... }
}

然而,这意味着使用 IDeepClonable 的任何代码本身必须变成泛型,这将变得笨重。
CLR 类型系统不够丰富,无法实现您真正想要的功能。

1
使用CRTP的一个问题是,可能会有一个包含可克隆和不可克隆派生类的基类,并且不可克隆的派生类可能具有可克隆的子派生类。将约束添加到“T”中是否允许做任何在其缺席时无法做的事情?此外,是否有任何理由不将“T”作为协变(“out”)类型参数? - supercat
这应该是逆变(in),而不是协变。 - hyankov

0
问题在于您在接口中声明了一个通用方法,而且您必须在派生类中完全按照该方法进行实现:
public class ClassA : IDeepClonable 
{ 
    void DeepClone<T>(T other) { /* some implementation here */ } 
} 

除此之外的任何东西都行不通。

话虽如此,为什么你需要这种复杂性呢?你不需要通用的东西,在这里只需实现:

public interface IDeepClonable 
{ 
    void DeepClone(IDeepClonable other); 
} 

public class ClassA : IDeepClonable 
{ 
    void DeepClone(IDeepClonable other)
    {
         // just to be sure ....
         if (other is ClassA) 
         {
             var o = (ClassA)other;
             this.A = o.A; 
         }
    } 
} 

谢谢您的回复。虽然如此,我还是希望能够避免这种实现方式。 - user981225

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接