C# 实现泛型方法
我用一种方法创建了一个接口,能够将一个对象的内容复制到同一类型的另一个对象中(实际功能与问题无关)C# 实现泛型方法,c#,.net,generics,c#-4.0,interface,C#,.net,Generics,C# 4.0,Interface,我用一种方法创建了一个接口,能够将一个对象的内容复制到同一类型的另一个对象中(实际功能与问题无关) 公共接口可理想化 { 无效克隆(T其他); } 我在正确的实现方面遇到了问题 我真正想要的是像这样实现它(这在ClassA中,它实现了IDeepClonable) public void DeepClone(A类其他) { 此.A=其他.A; } 但是,这不起作用,因为编译器不会将“other”对象识别为ClassA的实例(为什么?) 这也不起作用,因为它给出了一个“类型参数T的约束必须匹配(
公共接口可理想化
{
无效克隆(T其他);
}
我在正确的实现方面遇到了问题
我真正想要的是像这样实现它(这在ClassA中,它实现了IDeepClonable)
public void DeepClone(A类其他)
{
此.A=其他.A;
}
但是,这不起作用,因为编译器不会将“other”对象识别为ClassA的实例(为什么?)
这也不起作用,因为它给出了一个“类型参数T的约束必须匹配(…)接口方法”
public void DeepClone<T>(T other) where T : ClassA
{
this.A= other.A;
}
public void DeepClone(T other),其中T:ClassA
{
此.A=其他.A;
}
我可以通过将接口更改为接受对象而不是一般约束来解决所有问题,但我希望得到更优雅的解决方案
我也可以通过将接口转换为通用接口来解决这个问题,但这会迫使我转换为该通用接口。您正在尝试使用
你需要写作
public interface IDeepClonable<out T> where T : IDeepClonable<T>
{
void DeepClone(T other);
}
public class ClassA : IDeepClonable<ClassA> {
void DeepClone(ClassA other) { ... }
}
public interface IDeepClonable其中T:IDeepClonable
{
无效克隆(T其他);
}
公共类ClassA:理想可克隆{
void DeepClone(ClassA其他){…}
}
然而,这意味着任何使用IDeepClonable
的代码本身都必须是泛型的,这最终会变得笨拙
CLR类型系统不够丰富,无法实现您真正想要的功能。问题在于您在接口中声明了泛型方法,并且必须实现与派生类中完全相同的方法:
public class ClassA : IDeepClonable
{
void DeepClone<T>(T other) { /* some implementation here */ }
}
谢谢你的回复。不过我希望避免这种实现。顺便说一句,
DeepClone
是一个错误的名称;名为DeepClone
的方法应该返回一个副本。您应该将其命名为DeepCloneFrom
或类似的名称。我建议,如果您要进行大量深度克隆,最好使用方法T AsImmutable()
,IModifiableClone
使用方法U AsNewMutable()
,来定义iimmutableclone
,和IFullClone
继承上述两项。不可变对象只需从其AsImmutable()
实现返回自己AsNewMutable()
将返回至少允许U
契约所要求的任何突变方法的内容。在这里使用CRTP的一个问题是,一个人可能有一个基类,其中包括可克隆和不可克隆的派生,而不可克隆的派生可能有可克隆的子派生。将约束添加到T
是否允许一个人做任何在没有约束的情况下不能做的事情?还有,有什么理由不把T
设为协变(out
)类型参数吗?@supercat:我没想到。这应该是逆变的(in
),而不是协变的。
public interface IDeepClonable<out T> where T : IDeepClonable<T>
{
void DeepClone(T other);
}
public class ClassA : IDeepClonable<ClassA> {
void DeepClone(ClassA other) { ... }
}
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;
}
}
}