代码之家  ›  专栏  ›  技术社区  ›  santosh singh

在.NET中IClonable接口有什么用?

c#
  •  9
  • santosh singh  · 技术社区  · 15 年前

    5 回复  |  直到 15 年前
        1
  •  33
  •   Brian Gideon    15 年前

    嗯,其实不多。它在报纸上得到了特别的提及 Framework Design Guidelines

    不要实现ICloneable。在那里 有两种通用的实现方法 不可分离的,或者作为一个深的,或者 非深度复制。深度复制复制 克隆对象和所有对象 被对象递归引用 直到图形中的所有对象 如果只有最高层 引用被复制)可以不执行任何操作,或者 接口合同未指定 班级有不同的 实现。消费者不能 依靠ICloneable让他们知道 对象是深度克隆还是 不是。

    如果您想支持克隆,那么我将创建和实现单独的接口 IDeepCopy IShallowCopy 或者类似的。

        2
  •  5
  •   Andreas Paulsson    15 年前

    它是一个接口,如果实现它,它会发出信号,表示类的实例将被克隆,而不仅仅是浅层复制。不过,IClonable接口的实现并没有说明它是浅拷贝还是深拷贝。

    http://channel9.msdn.com/forums/TechOff/202972-IClonable-deep-vs-shallow-best-practise/ .

        3
  •  4
  •   Sergey Teplyakov    15 年前

    ICloneable Interface :

    支持克隆,这将创建一个新的 具有相同属性的类的实例 值作为现有实例。

    编辑: 斯科特·张伯伦完全正确。此接口未指定此副本应为深副本或浅副本。这是这个接口最让人困惑的地方之一。

        4
  •  1
  •   supercat    15 年前

    我想我找到了iCloneable的一个好用法:促进类层次结构的创建,包括可克隆和不可克隆类型。

    如果一个类有一个公共克隆方法,那么在不违反Liskov替换原则的情况下,就不可能从中派生出一个不能被有意义地克隆的类。问题是,对于任何给定的类来说,同时拥有一个可克隆的版本和一个允许不可克隆的派生类的版本可能都是有用的。iCloneable提供了一种方法。

    假设要定义类层次结构小部件、SuperWidget、SuperDuperWidget和SuperDuperNoncloneableWidget。Widget、SuperWidget和SuperDuperWidget都可以通过受保护的方法支持克隆。可以从它们派生类CloneableWidget、CloneableSuperWidget和CloneableSuperDuperWidget。

    如果不使用iCloneable(或类似的东西),那么编写一个既可以在CloneableWidget上操作,又可以在CloneableSuperWidget上操作的函数将非常困难。然而,使用iCloneable,可以让一个人的函数接受一个小部件,并且还要求它是iCloneable的。因此,这将允许一个人在所需的层次结构中很好地工作。

    请注意,与其他一些接口不同,iCloneable在隔离中没有意义。它仅在应用于可能公开或不公开支持克隆的类时用作类型约束;浅/深语义将是该类的语义。

        5
  •  0
  •   Matthew Brand    15 年前

    像这样定义IShallowClone和IDeepClone怎么样?

    public interface IShallowClone<T> { T ShallowClone(); }
    public interface IDeepClone<T> { T DeepClone(); }
    
    public interface IA : IShallowClone<IA>, IDeepClone<IA> { double a { get; } IA ia { get; } }
    public interface IB : IA, IShallowClone<IB>, IDeepClone<IB> { double b { get; } IB ib { get; } }
    
    public class A : IA
    {
        public double a { get; private set; } 
        public IA ia { get; private set; }
        public A(IA that) { this.a = that.a; this.ia = (ia as IDeepClone<IA>).DeepClone(); } 
        public IA DeepClone() { return new A(this); }
        public IA ShallowClone() { return this.MemberwiseClone() as IA; }
    }
    public class B : A, IB 
    { public double b { get; private set; } 
        public IB ib { get; private set; }
        public B(IB that) : base(that) { this.b = that.b; this.ib = (ib as IDeepClone<IB>).DeepClone(); } 
        public new IB DeepClone() { return new B(this); }
        public new IB ShallowClone() { return this.MemberwiseClone() as IB; }
    }