对象clone是一非常方便且有用的方法,在对数据的处理,尤其是大数据量的处理时,更觉可贵。

现谈下本人对对象clone的理解。

 

CLONE分为两种:深度clone(deep clone) 和 浅度clone(shallow clone). 都是 创建一与原对象具有相同类型的新实例。

但是有区别的,其创建过程不完全相同:

浅度clone(shallow clone): 创建与原始对象具有相同类型的新实例,然后复制原始对象的非静态字段(静态字段不属于类实例)。

     如果字段是值类型的,则对该字段 执行逐位复制。如果字段是引用类型,则复制该引用但不复制被引用的对象。

深度clone(deep clone): 创建与原始对象具有相同类型的新实例,然后复制原始对象的非静态字段(静态字段不属于类实例)。

     如果字段是值类型的,则对该字段 执行逐位复制。如果字段是引用类型,则复制该引用指向的实例而非复制该引用。

 

注意以上着为橙色的字体,区别就在此。可见,

相同点: clone所得对象与原对象的reference是不同的(因为不是一个实例),Equals的结果是false的(前提是没有override object's   Equals方法)。

区别: shallow clone的对象,其2级/3级/../n级引用对象的reference是相同的(因为是复制的reference,都指向同一实例),所以Equals(前提是没有override object's Equals方法)其对象关系网中的引用对象,是true的。

而deep clone的对象,是递归复制其对象关系网中的对象实例(而非引用),则Equals肯定是false的。

注意点: 无论deep or shallow clone,其进行的都是复制,而非new工作,所以类的初始化过程在clone中是不会产生的,即:成员初始化、类初始化等等,它仅是对已有对象的一个copy的,并将copy所得对象的heap address 赋值给新的reference的。

 

DEMO之:有对象X,A,B,C,X引用了A、B,A引用了C,伪代码演示如下:

 X.shallowClone();
X.Equals(Y) == FALSE;
X.A.Equals(Y.A) 
== TRUE;
X.B.Equals(Y.B) 
== TRUE;
X.A.C.Equals(Y.A.C) 
== TRUE;

 

 X.deepClone();
X.Equals(Y) == FALSE;
X.A.Equals(Y.A) 
== FALSE;
X.B.Equals(Y.B) 
== FALSE;
X.A.C.Equals(Y.A.C) 
== FALSE;

 

.NET中,Object默认所带的protected MemberwiseClone()方法,就是一个 shallow clone,要实现deep clone,

则要自己来实现的。.NET提供了一个接口IClone,是用来支持对象的deep clone的,但归根接底,还是要我们自己来实现clone()方法的,也就是说,实现该方法的不一定就是deep clone,甚至都不是clone,要看你是如何实现的,它仅是一个约束,要求你应该去这么做,但你不这么做,它也没办法(不过你不这么做,也只会给自己在使用中带来麻烦的)。

比如:我们看下.NET自己所实现IClone的几个类:Array 和 ArrayList,前者是shallow clone,后者则是deep clone的。

 Clone()
{
    return base.MemberwiseClone();
}

 

  Clone()
{
    
return base.MemberwiseClone();
}

 

 Clone()
{
    ArrayList list = new ArrayList(this._size);
    list._size 
= this._size;
    list._version 
= this._version;
    Array.Copy(
this._items, 0, list._items, 0this._size);
    
return list;
}

 

 

这里提供一个利用序列化进行deep clone方法的实现(前提,对象关系网中的对象必须是可序列化Serializable的)

 Object DeepClone()
        {    
            if (null == thisreturn null;
            
using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter 
= new BinaryFormatter();
                formatter.Serialize(stream,
this);
                stream.Position 
= 0;
                
return formatter.Deserialize(stream);
            }
        }

 

相关文章:

  • 2022-01-01
  • 2021-04-16
  • 2021-05-03
  • 2022-01-16
  • 2021-10-14
  • 2021-06-30
  • 2021-06-30
猜你喜欢
  • 2021-12-22
  • 2021-11-21
  • 2022-12-23
  • 2022-02-09
  • 2021-08-08
  • 2022-12-23
  • 2022-02-09
相关资源
相似解决方案