雁过请留痕...
代码改变世界

浅拷贝和深拷贝

2011-12-21 15:48  xiashengwang  阅读(340)  评论(0编辑  收藏  举报

 关于深拷贝和浅拷贝的区别,主要在对于引用类型的成员的拷贝上,浅拷贝只是简单的复制引用的地址,深拷贝会生成一个完全独立的对象,包括对象内的引用成员。

浅拷贝:Object类提供了一个MemberwiseClone方法,一般是基于它来实现。

深拷贝:要求对象要实现Serializable特性,表明它是可以被序列化的。利用对象的序列化和反序列化来实现深度拷贝。

完整的例子如下:

using System;
using System.Collections.Generic;
using System.Text;

namespace CsharpBase
{
    class CloneDemo
    {
        public static void Run()
        {

            People parent = new People("zhang", "30");
            parent.type = "old";
            parent.child.Name = "zhang xiao";
            parent.child.Age = "1";

            parent.PrintInfo();

            //浅拷贝
            People shallowParent = (People)parent.Clone();
            //深拷贝
            People deepParent = parent.DeepClone();

            shallowParent.type = "shallow";
            shallowParent.Name = "shallow zhang";
            //浅拷贝对于引用型成员child只会复制其所在堆的首地址,不会进行真正的内容拷贝
            //所以在这里shallowParent.child.Name的改变会导致parent.child.Name的改变,因为他们的
            //child都指向了同一片内存区
            shallowParent.child.Name = "shallow zhang xiao";
            shallowParent.PrintInfo();
            parent.PrintInfo();

            deepParent.type = "Deep";
            deepParent.Name = "Deep zhang";
            //深拷贝能实现真正的拷贝
            deepParent.child.Name = "Deep zhang xiao"; 
            deepParent.PrintInfo();
            parent.PrintInfo();
            Console.ReadKey();
        }

        [Serializable]
        private class People : ICloneable
        {
            public string type;
            public string Name;
            public string Age;
            public Child child = new Child();
            public People(string name, string age)
            {
                Name = name;
                Age = age;
            }

            //浅拷贝
            private People ShallowClone()
            {
                return (People)Clone();
            }

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

            //深拷贝
            public People DeepClone()
            {
                System.IO.Stream stream = new System.IO.MemoryStream();
                System.Runtime.Serialization.IFormatter formater = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                formater.Serialize(stream, this);
                stream.Seek(0, System.IO.SeekOrigin.Begin);

                return (People)formater.Deserialize(stream);
            }

            public void PrintInfo()
            {
                System.Diagnostics.Debug.WriteLine("type:" + type);
                System.Diagnostics.Debug.WriteLine("parent:" + Name);
                System.Diagnostics.Debug.WriteLine("child:" + child.Name);
                System.Diagnostics.Debug.WriteLine("---------------");
            }
        }

       [Serializable]
        private class Child
        {
            public string Name;
            public string Age;
        }

    }
}


注意,Child类也必须有Serializable特性,否则formater.Serialize(stream, this);的时候会抛出SerializableException异常。

运行结果:

type:old
 parent:zhang
 child:zhang xiao
 ---------------
 type:shallow
 parent:shallow zhang
 child:shallow zhang xiao
 ---------------
 type:old
 parent:zhang
 child:shallow zhang xiao  //这里被改变了
 ---------------
 type:Deep
 parent:Deep zhang
 child:Deep zhang xiao
 ---------------
 type:old
 parent:zhang
 child:shallow zhang xiao //这里没变
 ---------------