zoukankan      html  css  js  c++  java
  • 深度复制 与 浅度复制

    1.使用受保护的方法System.Object.MemberwiseClone()进行浅度复制。
    方法如下:
    public class Cloner
            
    {
                
    public int Val;

                
    public Cloner(int newVal)
                
    {
                    Val
    =newVal;
                }


                
    public object GetCopy()
                
    {
                    
    return MemberwiseClone();
                }

            }

    假定有引用类型的字段,而不是值类型的字段(例如,对象):
    public class Content
            
    {
                
    public int Val;
            }


            
    public class Cloner
            
    {
                
    public Content MyContent=new Content();

                
    public Cloner(int newVal)
                
    {
                    MyContent.Val
    =newVal;
                }


                
    public object GetCopy()
                
    {
                    
    return MemberwiseClone();
                }

            }
    此时,通过GetCopy()得到的浅度复制有一个字段,它引用的对象与源对象相同。
    下面的代码使用这个类来说明这一点:
      Cloner mySource=new Cloner(5);
      Cloner myTarget=(Cloner)mySource.GetCopy();
      Console.WriteLine("myTarget.MyContent.Val={0}",myTarget.MyContent.Val);
      mySource.MyContent.Val=2;
      Console.WriteLine("myTarget.MyContent.Val={0}".myTarget.MyContent.Val);
    第4行把一个值赋给MySource.MyContent.Val,源对象中公共域MyContent的公共域Val也改变了myTarget.MyContent.Val的值。这是因为mySource.MyContent引用了与myTarget.My.Content相同的对象实例。
    上述代码的结果如下:
    myTarget.MyContent.Val=5;
    myTarget.MyContent.Val=2;
    为了说明这个过程,需要执行深度复制。修改上面的GetCopy()方法就可以进行深度复制,但最好使用.Net FrameWork的标准方式。为此,实现ICloneable接口,该接口有一个方法Clone(),这个方法不带参数,返回一个对象类型,其签名和上面使用的GetCopy()方法相同。
    修改上面使用的类,可以使用下面的深度复制代码:

            
    public class Content
            
    {
                
    public int Val;
            }


            
    public class Cloner:ICloneable
            
    {
                
    public Content MyContent=new Content();

                
    public Cloner(int newVal)
                
    {
                    MyContent.Val
    =newVal;
                }


                
    public object Clone()
                
    {
                    Cloner clonedCloner
    =new Cloner(MyContent.Val)
                    
    return clonedCloner();
                }

            }
    其中使用包含在源Cloner对象(MyContent)中的Content对象的Val字段,创建一个新Cloner对象。这个字段是一个值类型,所以不需要深度复制。
    使用与上面类似的代码测试浅度复制,但使用Clone()而不是GetCopy(),得到如下结果:
    myTarget.MyContent.Val=5
    myTarget.MyContent.Val=5
    这次包含的对象是独立的。
    注意有时在比较复杂的对象系统中,调用Clone()是一个递归过程。例如,如果Cloner类的MyContent域也需要深度复制,就要使用下面的代码:
    public class Cloner:ICloneable
            
    {
                
    public Content MyContent=new Content();

                .

                
    public object Clone()
                
    {
                    Cloner clonedCloner
    =new Cloner();
                    clonedCloner.MyContent
    =MyContent.Clone();
                    
    return clonedCloner;
                }

            }

    这里调用了默认的构造函数,简化了创建一个新Cloner对象的方法。为了使这段代码能正常工作,还需要在Content类上实现ICloneable接口。

    //实现Clone()方法可以实现深层复制
     class test:ICloneable
        
    {
            
    public int a;
     
            
    ICloneable 成员
        }

        
    class Program
        
    {
            
           
            
    static void Main(string[] args)
            
    {
                test t1 
    = new test();
                t1.a 
    = 4;
                test t2
    =(test)t1.Clone();
                t2.a 
    = 8;
                Console.WriteLine(t1.a);
               
            }

        }

     
    //IClonable实现深度拷贝,举个例子 


    public class TDir : IClonable 

    private string[] _dirs; 
    private string[] _files; 

    public TDir() 

    _dirs 
    = null
    _files 
    = null
    }
     

    public object Clone() // deep copy 

    TDir copy 
    = new TDir(); 

    if (_dirs != null

    ArrayList list 
    = new ArrayList(_dirs.Length); 
    foreach (string i in _dirs) 
    list.Add(i); 
    copy._dirs 
    = (string[])list.ToArray(typeof(string)); 
    }
     

    if (_files != null

    ArrayList list 
    = new ArrayList(_files.Length); 
    foreach (string i in _files) 
    list.Add(i); 
    copy._files 
    = (string[])list.ToArray(typeof(string)); 
    }
     

    return copy; 
    }
     
    }

     
    通用的克隆方法:


            /// <summary>
            /// 克隆
            /// </summary>
            /// <returns></returns>
            public object Clone()
            {
                AwbBasic tObject = new AwbBasic();

                PropertyInfo[] pTar = this.GetType().GetProperties();
                PropertyInfo[] pSour = this.GetType().GetProperties();

                foreach (PropertyInfo s in pSour)
                {
                    foreach (PropertyInfo t in pTar)
                        {
                        if (s.Name == t.Name)
                        {
                            t.SetValue(tObject, s.GetValue(this, null), null);
                        }
                    }

                }

                return tObject;
            }

  • 相关阅读:
    Python3.8 爬取豆瓣电影TOP250 练手爬虫
    作为一名phper,php的运行模式,你真的了解吗??
    前端自动生成条码码插件JsBarcode.all.min.js
    js判断是否在微信内打开页面
    学习Swoole之如何避免成为被坑哭的程序员
    上下界网络流
    网络流建模经验
    HttpClient和Gson跨域访问
    CentOS7+mysql5.6配置主从
    Atlas安装配置
  • 原文地址:https://www.cnblogs.com/greatandforever/p/1326916.html
Copyright © 2011-2022 走看看