当前位置: 移动技术网 > IT编程>开发语言>.net > 浅谈.net平台下深拷贝和浅拷贝

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

2017年12月12日  | 移动技术网IT编程  | 我要评论
基本概念: 浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个

基本概念:

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

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

基本概念之参考代码:

复制代码 代码如下:

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


暂不做分析,认真领悟。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网