当 T 是 List<T> 时如何使用 ICloneable<T>?

sap*_*ket 5 c# icloneable

我有以下几点:

    public class InstanceList : List<Instance> {}
Run Code Online (Sandbox Code Playgroud)

我想让这个克隆。按照此处的示例:为什么没有 ICloneable<T>?

我尝试了以下方法:

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

    public class InstanceList : List<Instance>, ICloneable<List<Instance>>  {}
Run Code Online (Sandbox Code Playgroud)

但是我收到编译器错误。该错误消息指出 List<Instance> 必须转换为 ICloneable<List<Instance>> 以便在通用接口参数T使用 ICloneable<T>。

我在这里缺少什么?

Dav*_*ton 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();
}
Run Code Online (Sandbox Code Playgroud)

当然,您还可以采取另一种选择。您可以稍微扩展泛型来创建一个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();
}
Run Code Online (Sandbox Code Playgroud)

如果您真的想要变得更奇特,请创建一些将 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();
}
Run Code Online (Sandbox Code Playgroud)