zoukankan      html  css  js  c++  java
  • .net平台下深拷贝和浅拷贝

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

     

      在.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();
            }
        }
    复制代码

    暂不做分析,认真领悟。

    原创:ASP.Net状态管理读书笔记--思维导图

     

    导图文件下载

    课前提问几个问题

    使用Session

    配置

    model

    aspnet_regsql.exe

    常见问答

    问:为什么Session在有些机器上偶尔会丢失?
    答:可能和机器的环境有关系,比如:防火墙或者杀毒软件等,尝试关闭防火墙。

    问:为什么当调用Session.Abandon时并没有激发Session_End方法?
    答:首先Session_End方法只支持InProc(进程内的)类型的Session。其次要激发Session_End方法,必须存在Session(即系统中已经使用Session了),并且至少要完成一次请求(在这次请求中会调用该方法)。

    问:为什么每次请求的SessionID都不相同?
    答:该问题可能是没有在Session里面保存任何信息引起的,即程序中任何地方都没有使用Session。当Session中保存信息之后SessionID将一直和浏览器相关,此时的SessionID将不会在变化。

    问:当我使用InProc模式保存Session时,此时的Session是保存在哪里?
    答:不同的IIS的处理方式不同,
    当使用的是IIS5的时候Session是保存在aspnet_wp.exe的进程空间里的。
    当使用的是IIS6时,默认情况下所有的应用程序共享应用程序池,Session保存在w3wp.exe的进程空间中。

    问:Session的超时设置是分钟还是秒?
    答:是分钟,默认为20分钟。

     
     
    分类: ASP.NET
     
     
     
  • 相关阅读:
    Node.js v0.10.1 稳定版发布
    PHP 5.5.0 Alpha6 发布
    DataNucleus Access Platform 3.2 正式版发布
    Swipe 2.0 发布,移动端滑动 JS 库
    Kamailio 4.0 发布,开源的SIP服务器
    PeerJS 0.1.7:一个用于浏览器内P2P的WebRTC封装器
    Apache Libcloud 0.12.3 发布
    IE 10将加强对Flash的支持
    JBoss Portlet Bridge 3.2.0.Beta2 发布
    如何在遗留代码基础上开发
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3491553.html
Copyright © 2011-2022 走看看