如何使用 ICloneable当 T 是 List 时?

发布于 2024-11-27 13:30:34 字数 702 浏览 2 评论 0 原文

我有以下内容:

    public class InstanceList : List<Instance> {}

我想让它可克隆。按照此处的示例: 为什么没有 ICloneable

我尝试了以下操作:

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

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

但我得到了一个编译器错误。错误消息指出 列表<实例> 必须可转换为 ICloneable> 为了在通用接口中使用参数 T ICloneable

我在这里缺少什么?

I have the following:

    public class InstanceList : List<Instance> {}

I would like to make this cloneable. Following the example here: Why no ICloneable<T>?

I tried the following:

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

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

But I get a compiler error. The error message states that
List<Instance>
must be convertible to
ICloneable<List<Instance>>
in order to use parameter T in the generic interface
ICloneable<T>.

What am I missing here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情栀口红 2024-12-04 13:30:34

您不能这样做,因为您无法自己定义 List 。由于您限制 ICloneable 的方式,您只能声明自己的 List 才能执行此操作。由于 List 确实没有实现 ICloneable,因此您必须将 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 类型:

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 列表中的任何其他内容,从而以完全相同的方式对待每个 CloneableList方式,避免为您想要创建的每个可克隆列表使用不同的 ICloneable 实现。

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();
}

You can't do this, because you can't define List<T> yourself. You would only be able to do this if you could declare your own List<T> because of the way you've constrained ICloneable<T>. Since List<T> truly doesn't implement ICloneable<T>, you're going to have to have the type of T be InstanceList instead, which you do have control over.

Here's how you would implement it:

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();
}

Of course, there is another alternative you could do. You could widen your generics a little bit, to create a CloneableList<T> type:

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();
}

And if you really want to get fancy, create something that restricts T to ICloneable. Then you could implement ICloneable on the Instance class, and anything else you want to include in an ICloneable<T> list, thus treating every CloneableList<T> in the exact same way, avoiding a different implementation of ICloneable<T> for each and every cloneable list you want to create.

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();
}
晒暮凉 2024-12-04 13:30:34

问题是您的通用约束 where T : IClonable。因为您将界面“实例化”为 ICloneable>List 是您的 T,所以通用约束转换为 where List; :IClonable<列表<实例>List 不满足该约束。

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

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

The problem is your generic constraint where T : IClonable<T>. Because you're "instantiating" your interface as ICloneable<List<Instance>>, List<Instance> is your T, and so the generic constraint translates to where List<Instance> : IClonable<List<Instance>>. List<Instance> does not fulfill that constraint.

Perhaps you're trying to do something like this:

public interface ICloneableList<T> : ICloneable where T : ICloneable
{
}
不一样的天空 2024-12-04 13:30:34

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

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

实际上不应该是:

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

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

To add to the other good answers already there - when you clone, you expect to get an identical copy back, right? So instead of:

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

Shouldn't it actually be:

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

That way you will also get no compiler errors.

谁的新欢旧爱 2024-12-04 13:30:34

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

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

I don't think you can really do what you want. While it is useful not to require the type argument of ICloneable<T> to implement ICloneable<T>, I don't think the List<T> class can be very well extended to support cloning since it does not provide any means of detaching or duplicating the array which holds all the data items, does not allow a subclass access to that array, and does not allow a subclass to override enough virtual methods to render the array irrelevant. Although clone methods should start by using MemberwiseClone (to ensure that the cloned object is the same type as the original), there would be no guaranteed way to force the newly-cloned list to create a new array to hold its objects without disturbing the old one.

The closest thing I can suggest to doing what you want would be to define an ICloneableList<T> which inherits from IList<T> and ICloneable<IList<T>> and define an CloneableList class which implementats that by wrapping a list. Cloning a CloneableList should create a new List<T> with items copied from the old one, which can be done by using the appropriate constructor for the new List.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文