当T为List <t>?</t> </t>时,如何使用ICloneable <t>

时间:2011-08-02 18:43:14

标签: c# icloneable

我有以下内容:

    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> 必须可兑换成             ICloneable<List<Instance>> 为了在通用接口中使用参数T.             ICloneable<T>

我在这里缺少什么?

4 个答案:

答案 0 :(得分: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();
}

如果你真的想要获得幻想,可以创建一些限制T到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();
}

答案 1 :(得分: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
{
}

答案 2 :(得分:1)

要添加已经存在的其他好答案 - 当您克隆时,您希望获得相同的副本,对吧?所以而不是:

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

实际上不应该是:

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

这样你也不会遇到编译错误。

答案 3 :(得分:0)

我认为你不能真正做你想做的事。虽然不要求ICloneable&lt; T&gt;的类型参数是有用的。为了实现ICloneable&lt; T&gt;,我不认为List&lt; T&gt; class可以很好地扩展以支持克隆,因为它不提供任何分离或复制包含所有数据项的数组的方法,不允许子类访问该数组,并且不允许子类覆盖足够的虚方法使数组无关紧要。尽管克隆方法应该首先使用MemberwiseClone(以确保克隆对象与原始对象的类型相同),但是没有保证可以强制新克隆列表创建一个新数组来保存其对象而不会打扰旧对象之一。

我可以建议做你想做的最接近的事情是定义ICloneableList&lt; T&gt;继承自IList&lt; T&gt;和ICloneable&lt; IList&lt; T&gt;&gt;并定义一个CloneableList类,它通过包装列表来实现它。克隆CloneableList应该创建一个新的List&lt; T&gt;从旧的项目复制的项目,这可以通过使用新列表的相应构造函数来完成。