c#深拷贝与浅拷贝

来源:互联网 发布:四件套淘宝大品牌 编辑:程序博客网 时间:2024/06/05 17:14

转自:http://blog.csdn.net/xiaolei1982/article/details/2245480

 

今天特意研究下了深拷贝和浅拷贝:
首先介绍一下:
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
...{
publicclass   ClassA:ICloneable 
         
...
                 
publicint   Value  =0
                 
publicobject   Clone() 
                 
...
                         
returnthis.MemberwiseClone(); 
                  }
 
          }
 

         
publicclass   ClassB:ICloneable 
         
...
                 
public   ClassA   Member=new   ClassA(); 
                 
publicobject   Clone() 
                 
...
                         
//浅复制 
                         
//return   this.MemberwiseClone(); 
                          
                         
//深复制 
                          ClassB   obj=new   ClassB(); 
                         
//obj.Member=   (ClassA)Member.Clone(); 
return   obj; 
                  }
 
            }


          
publicclass class4
           
...{
               
publicstaticvoid  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
   
...{
       
publicclass Sex
       
...{
           
privatestring _PSex;
           
publicstring PSex
           
...{
               
set
               
...{
                    _PSex
= value;
                }

               
get
               
...{
                   
return _PSex;
                }

            }


        }


       
publicclass Person : ICloneable
       
...{
           
           
private Sex _pSex=new Sex();
           
publicint aa=1213;

           
publicstring pSex
           
...{
               
set
               
...{
                    _pSex.PSex
= value;
                }

               
get
               
...{
                   
return _pSex.PSex;
                }

            }

           
privatestring _PName;
           
publicstring PName
           
...{
               
set
               
...{
                   
this._PName = value;
                }

               
get
               
...{
                   
returnthis._PName;
                }

            }


           
publicvoid ShowPersonInfo()
           
...{
                Console.WriteLine(
"-------------------------");
                Console.WriteLine(
"Name:{0} Sex:{1}", _PName, this.pSex);
                Console.WriteLine(
"-------------------------");
                Console.WriteLine(
this.aa);
            }

           
//浅拷贝
publicobject Clone()
           
...{
               
returnthis.MemberwiseClone();
            }

           
//深拷贝
publicobject DeepClone()
           
...{
                Person newP
=new Person();
                newP.PName
=this._PName;
                newP.pSex
=this.pSex;
               
return newP;
            }


        }


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

提示:

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

看一下例子:

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

namespace WindowsApplication1
...{
   
class Class2
   
...{
      
publicstaticvoid Main()
       
...{
           
int[] numbers=...{2, 3,4, 5 };

           
int[] numbersCopy=newint[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
   
...{
       
publicstring aa="aa";
    }



   
class class4
   
...{
       
publicstaticvoid 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,那时因为两者都是浅拷贝,区别上面已经介绍了,所以

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

 

原创粉丝点击