2011-08-02 30 views
4

我有以下几点:如何使用ICloneable <T>当T是列表<T>?

public class InstanceList : List<Instance> {} 

我想使这个可复制的。这里继例如:Why no ICloneable<T>?

我试过如下:

public interface ICloneable<T> : ICloneable Where T : ICloneable<T> 
      {  new T Clone(); } 

    public class InstanceList : List<Instance>, ICloneable<List<Instance>> {} 

但我得到一个编译错误。该错误消息指出 List<Instance> 必须为了使用参数T在通用接口 ICloneable<T>转换为 ICloneable<List<Instance>>

我在这里错过了什么?

回答

4

你不能这样做,因为你不能定义List<T>自己。如果您可以声明自己的List<T>,那么您将只能这样做,因为您限制的方式为ICloneable<T>。由于List<T>确实不会实现ICloneable<T>,因此您将不得不将T的类型替换为InstanceList,您可以使用执行的控制。

这里是你将如何实现它:

public class InstanceList : List<Instance>, ICloneable<InstanceList> 
{ 
    public InstanceList Clone() 
    { 
     // Implement cloning guts here. 
    } 

    object ICloneable.Clone() 
    { 
     return ((ICloneable<InstanceList>) this).Clone(); 
    } 
} 

public class Instance 
{ 

} 

public interface ICloneable<T> : ICloneable where T : ICloneable<T> 
{ 
    new T Clone(); 
} 

当然,还有另外一种选择,你可以做。你可以扩大你的泛型一点点,创建一个CloneableList<T>类型:

public class CloneableList<T> : List<T>, ICloneable<CloneableList<T>> 
{ 
    public CloneableList<T> Clone() 
    { 
     throw new InvalidOperationException(); 
    } 

    object ICloneable.Clone() 
    { 
     return ((ICloneable<CloneableList<T>>) this).Clone(); 
    } 
} 

public interface ICloneable<T> : ICloneable where T : ICloneable<T> 
{ 
    new T Clone(); 
} 

如果你真的想获得幻想,创造一些限制吨至ICloneable。然后,您可以在Instance类上实现ICloneable,并且可以在ICloneable<T>列表中包含任何其他内容,从而以完全相同的方式处理每个CloneableList<T>,从而为您要创建的每个可复制列表避免不同的ICloneable<T>实现。

public class CloneableList<T> : List<T>, ICloneable<CloneableList<T>> where T : ICloneable 
{ 
    public CloneableList<T> Clone() 
    { 
     var result = new CloneableList<T>(); 
     result.AddRange(this.Select(item => (T) item.Clone())); 
     return result; 
    } 

    object ICloneable.Clone() 
    { 
     return ((ICloneable<CloneableList<T>>) this).Clone(); 
    } 
} 

public interface ICloneable<T> : ICloneable where T : ICloneable<T> 
{ 
    new T Clone(); 
} 
+0

这工作。一个变化:T克隆();需要新的关键字来覆盖object.Clone()。我现在看到我的想法是不正确的。我克隆的类别不是列表。谢谢! – sapbucket

+0

请务必查看我所做的修改。第二个和第三个选项比我列出的第一个选项灵活得多。 –

+0

为什么它需要第二个对象ICloneable.Clone()方法?我认为这个接口只需要一个Clone()操作的方法。 – sapbucket

2

问题是您的通用约束where T : IClonable<T>。因为“实例化”您的界面为ICloneable<List<Instance>>,所以List<Instance>是您的T,所以通用约束转换为where List<Instance> : IClonable<List<Instance>>List<Instance>不符合该限制。

也许你正在试图做这样的事情:

public interface ICloneableList<T> : ICloneable where T : ICloneable 
{ 
} 
+0

如果我这样做,这样我得到'公共类InstanceList:列表,ICloneable {公共对象的clone(){}}” – sapbucket

+0

...并返回类型为对象,而不是类型列表 sapbucket

+0

我省略了方法,但它仍然需要它。我只是指出通用约束是错误的。 – Jacob

1

要添加到其他好的答案已经存在 - 当你克隆,你希望得到一个相同的拷贝过来的,对不对?因此,而不是:

public class InstanceList : List<Instance>, ICloneable<List<Instance>> {} 

难道不应该实际上是:

public class InstanceList : List<Instance>, ICloneable<InstanceList> {} 

这样,你也不会得到编译器错误。

+0

没错,那是解决错误的答案。本着社区的精神,我认为David给我展示了一个更好的实现方式,他最初指出了你上面展示的内容。 – sapbucket

0

我不认为你真的可以做你想做的。虽然有必要不要求ICloneable的类型参数实现ICloneable <T>,但我不认为List可以很好地扩展以支持克隆,因为它不提供任何分离方法或者复制包含所有数据项的数组,不允许子类访问该数组,并且不允许子类重写足够的虚拟方法来呈现数组。虽然克隆方法应该使用MemberwiseClone开始(为了确保克隆的对象与原始对象类型相同),但不会保证强制新克隆的列表创建一个新的数组来保存它的对象而不会干扰旧的一。

我可以建议做你想要将定义一个ICloneableList <牛逼>其自IList <牛逼>和ICloneable < IList的<牛逼> >继承并定义一个CloneableList类implementats什么最接近的事,通过包装一名单。克隆一个CloneableList应该创建一个新的列表<T>,从旧的列表复制项目,这可以通过使用适当的新列表构造函数来完成。