欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-02-28 15:09:40
基本概念: 浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个...

基本概念:

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

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

基本概念之参考代码:

复制代码 代码如下:

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


暂不做分析,认真领悟。