5

我有以下内容:

    public class InstanceList : List<Instance> {}

我想让这个可以克隆。按照此处的示例:为什么没有 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

4 回答 4

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();
}
于 2011-08-02T18:49:22.267 回答
2

问题是您的通用约束where T : IClonable<T>。因为您将接口“实例化”为ICloneable<List<Instance>>, List<Instance>is your T,所以通用约束转换为where List<Instance> : IClonable<List<Instance>>. List<Instance>不满足该约束。

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

public interface ICloneableList<T> : ICloneable where T : ICloneable
{
}
于 2011-08-02T18:48:16.363 回答
1

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

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

实际上不应该是:

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

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

于 2011-08-02T18:59:34.480 回答
0

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

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

于 2011-09-22T17:31:20.160 回答