深拷贝和浅拷贝

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

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

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

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


 

ExpandedBlockStart.gif 代码
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()在上面已经介绍过了,通过实例可以清楚看到浅拷贝与深拷贝的区别

 

 

ExpandedBlockStart.gif 代码
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  =  ...{  2 3 4 5 };

   
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()方法只是传送了阶数相同、有足够元素空间的已有数组。

提示:

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

看一下例子:

 

 

 

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

namespace  WindowsApplication1
...{
    
class  Class2
    ...{
       
public   static   void  Main()
        ...{
            
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 ]);

            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.youkuaiyun.com/xiaolei1982/archive/2008/04/02/2245480.aspx

转载于:https://www.cnblogs.com/zhangzt/archive/2010/07/29/1788062.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值