zoukankan      html  css  js  c++  java
  • 深拷贝和浅拷贝

    首先介绍一下:
    C#中有两种类型变量,一种 是值类型变量,一种是引用类型变量。对于前者,copy是属于全盘复制;而对于后者,一般的copy只是浅copy,相当于只传递一个引用指针一样。因此 对于后者进行真正copy的时候,也是最费事的,具体的说,必须为其实现ICloneable接口中提供的Clone方法。

    浅拷贝(影子克隆):只复制对象的基本类型,对象类型,仍属于原来的引用.
    深拷贝(深度克隆):不紧复制对象的基本类,同时也复制原对象中的对象.就是说完全是新对象产生的.

    浅 拷贝和深拷贝之间的区别:浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象 中引用型字段的值他将反映在原是对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一 个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对 象中对应字段的内容。所以对于原型模式也有不同的两种处理方法:对象的浅拷贝和深拷贝。

    MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用 类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。深拷贝,即实现ICloneable接口.ICloneable可用于深拷贝 和浅拷贝。%Á÷ajØ7NKwww.pin5i.com6̎~ÜK-H}c
    这些都是概念,但是需要我们理解,下面介绍实例:


     

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace WindowsApplication1
    ...{
    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;  
                      }  
                } 
     
               
    public class class4
                ...{
                    
    public static void  Main()
                     ...{
                                ClassB   sb   
    =   new ClassB();  
                                sb.Member.Value     
    =   15;  
                                                   
                                ClassB   nb   
    =   (ClassB)sb.Clone();  
                                nb.Member.Value     
    =   6;
                               Console.Write(sb.Member.Value.ToString() 
    + "---" + nb.Member.Value.ToString());                
                               ClassA nnb 
    = new ClassA();
                                nnb.Value 
    = 111;
                               ClassA bbn 
    = new ClassA();
                               bbn 
    = (ClassA)nnb.Clone();
                               bbn.Value 
    = 222;
                               Console.Write(bbn.Value);
                               Console.Read();

                        }
                }
    }

    其中.MemberwiseClone()在上面已经介绍过了,通过实例可以清楚看到浅拷贝与深拷贝的区别

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace WindowsApplication1
    ...{
        
    class Program
        ...{
            
    public class Sex
            ...{
                
    private string _PSex;
                
    public string PSex
                ...{
                    
    set
                    ...{
                        _PSex 
    = value;
                    }
                    
    get
                    ...{
                        
    return _PSex;
                    }
                }

            }

            
    public class Person : ICloneable
            ...{
                
                
    private Sex _pSex = new Sex();
                
    public int aa = 1213;

                
    public string pSex
                ...{
                    
    set
                    ...{
                        _pSex.PSex 
    = value;
                    }
                    
    get
                    ...{
                        
    return _pSex.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;
                }

            }

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


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


                Console.WriteLine(
    "修改后的原对象:");
                p.PName 
    = "JackZhao";
                p.pSex 
    = "";
                p.aa 
    = 1111;
                p.ShowPersonInfo();


                Console.WriteLine(
    "修改后的浅拷贝对象:");
                copy.ShowPersonInfo();
                Console.WriteLine(
    "修改后的深拷贝对象:");
                dcopy.ShowPersonInfo();

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

                Console.ReadLine();


            }

        }
    }

     


    接下来介绍一下数组的拷贝:
     int [] numbers = ...{ 2345};

       
    int [] numbersCopy = numbers;

    numbersCopy[
    2= 0;

          Console.Write(numbers[
    2]);

               Console.Write(numbersCopy[
    2]);

    首先数组的直接拷贝也就是复制,不用多说看例子:

    结果就是
    0

    0

    道理很简单,数组的复制也就是引用传递,指向的是同一个地址,这不是我们介绍的重点

    接下来

    看一下概念

    数组是引用类型,所以将一个数组变量赋予另一个数组变量,就会得到两个指向同一数组的变量。而复制数组,会使数组实现ICloneable接口。这个接口定义的Clone()方法会创建数组的浅副本。

    如果数组的元素是值类型,就会复制所有的值,如果数组包含引用类型,则不复制元素,而只复制引用,

    除了使用Clone()方法之外,还可以使用Array.Copy()方法创建浅副本。但Clone()方法和Copy()方法有一个重要区别:Clone()方法会创建一个新数组,而Copy()方法只是传送了阶数相同、有足够元素空间的已有数组。

    提示:

    如果需要包含引用类型的数组的深副本,就必须迭代数组,创建新对象。

    看一下例子:

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace WindowsApplication1
    ...{
        
    class Class2
        ...{
           
    public static void Main()
            ...{
                
    int[] numbers = ...{ 2345 };

                
    int[] numbersCopy = new int[5];

                numbers.CopyTo(numbersCopy,
    0);

                numbersCopy[
    2= 0;

                
    int[] numbers1 = ...{ 2345 };

                
    int[] numbersClone1 = (int[])numbers1.Clone();

                numbersClone1[
    2= 0;

                Console.Write(numbers[
    2+ "---" + numbersCopy[2]);

                Console.Read();


            }
        }
    }
    我这里介绍的主要是数组的clone和copyto的用法,两者都不会改变其中的值,与上面我们的复制有很大的区别 
    因为数组里面是值类型,所以他们不存在引用,而


     
    class class1
        ...{
            
    public string aa = "aa";
        }


        
    class class4
        ...{
            
    public static void Main()
            ...{
               
                class1 aaa 
    = new class1();
                class1[] array3 
    = new class1[1];
                class1[] array4 
    = new class1[1];
                array3[
    0= aaa;
                
    //Array.Copy(array3, 0, array4, 0,1);
                array3.CopyTo(array4, 0);
                
    //array4=(class1[])array3.Clone();
                array3[0].aa = "bb";

                Console.Write(array4[
    0].aa);
                Console.Read();
            }
        }

    结果是两者都改变了值,最后输出都是bb,那时因为两者都是浅拷贝,区别上面已经介绍了,所以

    都没有实现深拷贝,以上如果分析有错误请大家指出,这只是我这么认为!

    [文章出处]http://blog.csdn.net/xiaolei1982/archive/2008/04/02/2245480.aspx

    该文章经过本人整理所得,欢迎转载,转载时请加上本文地址;本文基于署名 2.5 中国大陆许可协议发布,请勿演绎或用于商业目的,但是必须保留本文的署名张志涛(包含链接如您有任何疑问或者授权方面的协商,请给我留言
  • 相关阅读:
    后端PHP框架laravel学习踩的各种坑
    IE6、IE7兼容querySelectorAll和querySelector方法-最终版本
    package.json保存
    原生javascript兼容性总结
    原生javascript代码懒加载
    禁止选择文本样式
    xml转实体类的实现
    kendo ui editor 文本编辑器 自定义高度的实现
    setTimeout执行时带参数,并且带的是object对象类型的参数
    KendoUi listview template的用法记录
  • 原文地址:https://www.cnblogs.com/zhangzt/p/1788062.html
Copyright © 2011-2022 走看看