浅拷贝 深拷贝

所谓浅拷贝就是将对象中的所有字段复制到新的副本对象中;浅拷贝对于值类型与引用类型的方式有区别,值类型字段的值被复制到副本中后,在副本中的修改不会影响源对象对应的值;然而对于引用类型的字段被复制到副本中的却是引用类型的引用,而不是引用的对象,在副本中对引用类型的字段值被修改后,源对象的值也将被修改。

深拷贝也同样是将对象中的所有字段复制到副本对象中,但是,无论对象的值类型字段或者引用类型字段,都会被重新创建并复制,对于副本的修改,不会影响到源对象的本身;

这里我们需要注意一点Student中的IDCode属性是string类型,理论上string类型是引用类型,但是由于该引用类型的特殊性,Object.MemberwiseClone方法仍旧为他创建了副本,也就是说,在浅拷贝过程中,我们应该将字符串看成值类型;

建议使用序列化的形式来进行深拷贝

#region 拷贝主体
        /// <summary>
        /// 深度拷贝
        /// </summary>
        /// <returns></returns>
        public Student DeepClone() {
            using (Stream objectStream = new MemoryStream()) {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(objectStream, this);
                objectStream.Seek(0,SeekOrigin.Begin);
                return formatter.Deserialize(objectStream) as Student;
            }
        }

        public object Clone()
        {
            return this.MemberwiseClone();
        }
        #endregion


MemberwiseClone:创建当前 Object 的浅表副本。
MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,
则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。


对于引用类型的变量,我们有种误解,认为赋值操作就是浅拷贝一种,其实不然,两者有区别。
  1. 浅拷贝(shallow copy)对于引用类型对象中的值类型字段进行了逐位复制。赋值运算符只是把源对象的引用赋值给目的对象,两者引用同一个对象。
  2. 浅拷贝后的对象的值类型字段更改不会反映到源对象,而赋值运算后的对象的值类型字段更改会反映到源对象
在C#中,我们们有三种方法实现深拷贝
    1. 实现ICloneable接口,自定义拷贝功能。
      ICloneable 接口,支持克隆,即用与现有实例相同的值创建类的新实例。
      ICloneable 接口包含一个成员 Clone,它用于支持除 MemberwiseClone 所提供的克隆之外的克隆。Clone 既可作为深层副本实现,也可作为浅表副本实现。在深层副本中,所有的对象都是重复的;而在浅表副本中,只有顶级对象是重复的,并且顶级以下的对象包含引用。 结果克隆必须与原始实例具有相同的类型或是原始实例的兼容类型。
      序列化是将对象或对象图形转换为线性字节序列,以存储或传输到另一个位置的过程。反序列化是接受存储的信息并利用它重新创建对象的过程。
      通过 ISerializable 接口,类可以执行其自己的序列化行为。
      转换为线性字节序列后并利用其重新创建对象的过程是不是和我们的深拷贝的语意“逐位复制”很相像?浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝。
原文地址:https://www.cnblogs.com/Fred1987/p/6002883.html