在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力。所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的

基本概念:

浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个对象。大部分的引用类型,实现的都是浅拷贝,引用类型对象之间的赋值,就是复制一个对象引用地址的副本,而指向的对象实例仍然是同一个。

深拷贝:指对象的子段被拷贝,同时字段引用的对象也进行了拷贝。深拷贝创建的是整个源对象的结构,拷贝对象和原对象相互独立,不共享任何实例数据,修改一个对象不会影响到另一个对象。值类型之间的赋值操作,执行的就是深拷贝。

基本概念之参考代码:

class Program
    {
        static void Main(string[] args)
        {
            Student s1 = new Student("li", 23);

//浅拷贝
            Student s2 = s1;
            s2.Age = 27;
            s1.ShowInfo();//li's age is 27

//深拷贝
            int i = 12;
            int j = i;
            j = 22;
            Console.WriteLine(i);//12

Console.Read();
        }
    }

class Student
    {
        public string Name;
        public int Age;

public Student(string name, int age)
        {
            Name = name;
            Age = age;
        }

public void ShowInfo()
        {
            Console.WriteLine("{0}'s age is {1}", Name, Age);
        }
    }

分析:

在上例中,实例s2对s1进行了浅拷贝,对s2中的Age字段进行更改,继而影响实例s1中的Age字段。

深拷贝中,仅仅是值类型间简单的赋值,对“j”做出的更改不会更改“i”的值。

深浅拷贝的实现:

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

MemberwiseClone:创建一个浅表副本。过程是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用对象。

参考代码:

class Program
    {
        static void Main(string[] args)
        {
            ClassA ca = new ClassA();
            ca.value = 88;
            ClassA ca2 = new ClassA();
            ca2 = (ClassA)ca.Clone();
            ca2.value = 99;
            Console.WriteLine(ca.value + "-----" + ca2.value);//88---99

ClassB cb = new ClassB();
            cb.Member.value = 13;

ClassB cb2 = (ClassB)cb.Clone();
            cb2.Member.value = 7;
            Console.WriteLine(cb.Member.value.ToString() + "------" + cb2.Member.value.ToString());//浅拷贝:7---7      深拷贝:13----7

Console.Read();
        }
    }

public class ClassA : ICloneable
    {
        public int value = 0;

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

public class ClassB : ICloneable
    {
        public ClassA Member = new ClassA();

public object Clone()
        { 
            //浅拷贝
            return this.MemberwiseClone();

//深拷贝
            ClassB obj = new ClassB();
            obj.Member = (ClassA)Member.Clone();
            return obj;
        }
    }

分析:

上例中,ca2复制ca对象,实现了深度拷贝。结果如同代码中显示:ca2中值类型字段的改变并不影响ca中的字段。

在类ClassB中,引用类型成员Member,如果用ClassA中的clone方法实现则仅仅实现的是浅拷贝,在上述参考代码中能够看出:对cb2的member的改变影响着cb。但是当使用参考代码中的深度拷贝后,对cb2的member的改变则不会影响着cb。

在网上找到一个综合的例子,有对比的来进行解释深浅拷贝:

实例1:

public class Sex:ICloneable 
    {
        private string _PSex;
        public string PSex
        {
            set{ _PSex = value;}
            get { return _PSex; }
        }

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

public class Person : ICloneable
    {

private Sex sex = new Sex();
        public int aa = 3;

public string pSex
        {
            set { sex.PSex = value; }
            get { return sex.PSex; }
        }
        private string _PName;
        public string PName
        {
            set { this._PName = value; }
            get { return this._PName; }
        }

public void ShowPersonInfo()
        {
            Console.WriteLine("-------------------------");
            Console.WriteLine("Name:{0} Sex:{1}", _PName, this.pSex);
            Console.WriteLine("-------------------------");
            Console.WriteLine(this.aa);
        }
        //浅拷贝
        public object Clone()
        {
            return this.MemberwiseClone();
        }
        //深拷贝
        public object DeepClone()
        {
            Person newP = new Person();
            newP.PName = this._PName;
            newP.pSex = this.pSex;
            return newP;
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("原对象:");
            Person p = new Person();
            p.PName = "Lee";
            p.pSex = "男";

p.ShowPersonInfo();//原对象:lee 男 3

//浅拷贝        
            Person copy = (Person)p.Clone();
            //深拷贝
            Person dcopy = (Person)p.DeepClone();

Console.WriteLine("修改后的原对象:");
            p.PName = "Zhao";
            p.pSex = "女";
            p.aa = 1;
            p.ShowPersonInfo();//zhao 女 1

Console.WriteLine("修改后的浅拷贝对象:");
            copy.ShowPersonInfo();//lee 女 3

Console.WriteLine("修改后的深拷贝对象:");
            dcopy.ShowPersonInfo();//lee 男 3

Console.WriteLine("直接拷贝对象:");
            Person PP = p;
            PP.ShowPersonInfo();//zhao 女 1

Console.ReadLine();
        }
    }

分析:

首先需指出,上例中在类Sex中,加入Clone方法和不加对实例中运算结果没有影响。

类Person中,引用类型但却是string类型的PName字段,引用类型pSex字段,值类型aa。

初始值:lee 男 3  (先进行深浅拷贝)

修改值:zhao 女 1

浅拷贝值:lee 女 3

深拷贝值:lee 男 3

直接拷贝值:赵 女 1

结果:上述可以说是对深浅拷贝中经常遇到的几种类型做出总结和对比,相信在一番体悟后可以学到一些知识。

实例2:

class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 2, 3, 4, 5 };
            int[] numbersCopy = new int[5];
            numbers.CopyTo(numbersCopy, 0);
            numbersCopy[2] = 0;

int[] numbers1 = { 2, 3, 4, 5 };
            int[] numbersClone1 = (int[])numbers1.Clone();
            numbersClone1[2] = 0;

Console.Write(numbers[2] + "---" + numbersCopy[2]);//4---0
            Console.Write(numbers1[2] + "---" + numbersClone1[2]);//4--0

//数组的复制也就是引用传递,指向的是同一个地址
            int[] numbers2 = { 2, 3, 4, 5 };
            int[] numbers2Copy = numbers2;
            numbers2Copy[2] = 0;

Console.Write(numbers2[2]);//0
            Console.Write(numbers2Copy[2]);//0

Console.Read();
        }
    }

浅谈.net平台下深拷贝和浅拷贝的更多相关文章

  1. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  2. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  3. .net平台下深拷贝和浅拷贝

    在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的. ...

  4. 浅谈python 复制(深拷贝,浅拷贝)

    博客参考:点击这里 python中对象的复制以及浅拷贝,深拷贝是存在差异的,这儿我们主要以可变变量来演示,不可变变量则不存在赋值/拷贝上的问题(下文会有解释),具体差异如下文所示 1.赋值: a=[1 ...

  5. java基础(十七)----- 浅谈Java中的深拷贝和浅拷贝 —— 面试必问

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

  6. 浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍

    浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍 前记 自己是搞编程的,首先我是一个菜鸟,接触计算机这么久了,感觉很多计算机方面的技术和知识朦朦胧胧.模模糊糊,貌似有些贻笑大方了:所 ...

  7. 浅谈C#中的深拷贝(DeepCopy)与浅拷贝(MemberwiseClone)

    场景:MVVM模式中数据双向绑定,想实现编辑.保存.撤销操作时也双向绑定了,不能实现撤销操作. 后来通过搜索找到了继承IEditableObject接口实现撤销操作,但是对其中使用了Memberwis ...

  8. 浅谈python中的赋值、浅拷贝与深拷贝:

    1.赋值----------是对原对象的引用,指向同一片内存地址 浅拷贝和深拷贝对于容器类型对象才有意义 2.浅拷贝----------对于一个对象的顶层进行拷贝 浅拷贝有三种方式: (1)切片 (2 ...

  9. 浅谈SDN架构下的运维工作

    导读 目前国内的网络运维还处于初级阶段,工作人员每天就像救火一样,天天疲于奔命.运维人员只能埋头查找系统运行的日志,耗时耗力,老眼昏花不说,有时候忙了半天还一无所获,作为运维工程师的你,有木有遇到过类 ...

随机推荐

  1. Fatal error: Maximum execution time of 30 seconds exceeded in

    Fatal error: Maximum execution time of 30 seconds exceeded in C:\Program Files\Apache Software Found ...

  2. iOS:Masonry 英文原档介绍

    Masonry 英文原档介绍: Masonry is still actively maintained, we are committed to fixing bugs and merging go ...

  3. linux中查找文件属于那个软件包的方法

    一.linux中查找文件属于那个软件包的方法 [root@salt prod]# whereis htpasswdhtpasswd: /usr/bin/htpasswd /usr/share/man/ ...

  4. JAVA加解密 -- Base64加解密

    Base64算法实现:可以将任意的字节数组数据,通过算法,生成只有(大小写英文.数字.+./)(一共64个字符)内容表示的字符串数据. private static final String str ...

  5. java8 环境变量设置

    Java8环境变量配置:a.JAVA_HOME:jdk安装目录b.CLASSPATH:.;%JAVA_HOME%\libc.PATH:%JAVA_HOME%\bin配置环境变量方法:1.点击计算机,右 ...

  6. jQuery find() 搜索所有段落中的后代 C# find() 第一个匹配元素 Func 有返回值 Action是没有返回值 Predicate 只有一个参数且返回值为bool 表达式树Expression

    所有p后代span Id为 TotalProject 的 select 标签 的后代 option标签 为选中的 text using System; using System.Collections ...

  7. Atitit.手机验证码的破解---伪随机数

    Atitit.手机验证码的破解---伪随机数 1. 手机验证码几乎都是伪随机数1 2. 伪随机数1 2.1. 生成方法编辑1 2.2. 随机数的计算方法在不同的计算机中是不同的,即使在相同的计算机中安 ...

  8. GTS、GCK,GSR全称

    GTS:Global 3-state buffer delay 全局使能,三态 GCK:Global Clock buffer delay   全局时钟 GSR:Global set/reset bu ...

  9. android studio- Gradle "xxx" project refresh failed

    Android Studio每次更新版本都会更新Gradle这个插件,但由于长城的问题每次更新都是失败,又是停止在Refreshing Gradle Project ,有时新建项目的时候报 Gradl ...

  10. awk按列求和

    awk 'BEGIN{total=0}{total+=$1}END{print total}'