【问题标题】:Implementing a Generic method实现通用方法
【发布时间】:2012-05-07 15:53:30
【问题描述】:

我用一种方法创建了一个接口,能够将一个对象的内容复制到另一个相同类型的对象中(实际功能与问题无关)。

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

我无法正确实施。

我真正想要的是像这样实现它(这是在 ClassA 内部,它实现了 IDeepClonable)

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

但这不起作用,因为编译器不会将“其他”对象识别为 ClassA 的实例(为什么?)

这也不起作用,因为它给出了“类型参数 T 的约束必须匹配 (...) 接口方法。

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

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

我也可以通过将接口转换为泛型接口来解决这个问题,但这会迫使我强制转换为该泛型接口。

【问题讨论】:

  • 顺便说一句,DeepClone 是错误的名称;一个名为DeepClone 的方法应该返回一个副本。您应该将其命名为 DeepCloneFrom 或类似名称。
  • 我建议,如果您要进行大量深度克隆,最好使用方法 T AsImmutable() 定义 IImmutableClonable&lt;T&gt;,使用方法 IModifiableClone&lt;U&gt; 和方法 U AsNewMutable()IFullClone&lt;T,U&gt; 继承了上述两个。不可变对象只会从它们的AsImmutable() 实现中返回自己; AsNewMutable() 将返回至少允许U 的合同要求的任何突变方法的东西。

标签: c# .net generics c#-4.0 interface


【解决方案1】:

您正在尝试使用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 类型系统不够丰富,无法满足您的需求。

【讨论】:

  • 这里使用 CRTP 的一个问题是,一个基类可能包含可克隆和不可克隆的衍生物,而不可克隆的衍生物可能具有可克隆的子衍生物。将约束添加到T 是否允许一个人做任何在它不在时不能做的事情?另外,是否有任何理由不将T 设为协变(out)类型参数?
  • @supercat:我没想到。
  • 这应该是逆变的 (in),而不是协变的。
【解决方案2】:

问题是你在接口中声明了一个泛型方法,你必须在派生类中实现完全一样的方法:

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; 
         }
    } 
} 

【讨论】:

  • 感谢您的回复。不过,我希望避免这种实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 2012-07-28
  • 2020-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多