C#對象復制 ICloneable


.net framework中,提供了ICloneable接口來對對象進行克隆。當然,你也可以不去實現ICloneable接口而直接自己定義一個Clone()方法,當然,還是推薦實現ICloneable接口。

具體實現方法

using UnityEngine;
using System.Collections;
using System;  
using System.IO;  
using System.Runtime.Serialization;  
using System.Runtime.Serialization.Formatters.Binary;  

[Serializable]  
public class Job  
{  
    public int id;
    public string JobName { get; set; }  
    public override string ToString()  
    {  
        return this.JobName;  
    } 
    public int ID 
    {
        get { return id;}
        set { id = value;}
    } 
}

[Serializable]  
public class Person:ICloneable   
{  
    public int Age { get; set; }  //值類型字段  
    public string Name { get; set; }  //字符串  
    public Job Job { get; set; }  //引用類型字段  

    //深拷貝  
    public Person DeepClone()  
    {  
        using (Stream objectStream = new MemoryStream())  
        {  
            IFormatter formatter = new BinaryFormatter();  
            formatter.Serialize(objectStream,this);  
            objectStream.Seek(0, SeekOrigin.Begin);  
            return formatter.Deserialize(objectStream) as Person;  
        }  
    }  

    public object Clone()  
    {  
        return this.MemberwiseClone();  //淺拷貝
    }  

    //淺拷貝  
    public Person ShallowClone()  
    {  
        return this.Clone() as Person;  
    }  
}  

測試案例:

 

using UnityEngine;
using System.Collections;

//測試C# 類拷貝
public class ClassCloneTest : MonoBehaviour {

    // Use this for initialization
    void Start () 
    {
        Person p = new Person() { Name = "test0001", Age = 20,Job = new Job(){JobName="Coder",ID = 100022 } };  
        
        string Str = "";
        
        Str = string.Format("修改前:p.Name={0},p.Age={1},p.Job.JobName={2}", p.Name, p.Age, p.Job.JobName); 

        
        Person p1 = p.ShallowClone();  
        Person p2 = p.DeepClone();  

        
        Debug.Log(Str); 
        Str = string.Format("修改前:p1.Name={0},p1.Age={1},p1.Job.JobName={2}", p1.Name, p1.Age, p1.Job.JobName); 
        Debug.Log(Str);  
        Str = string.Format("修改前:p2.Name={0},p2.Age={1},p2.Job.JobName={2}", p2.Name, p2.Age, p2.Job.JobName);  
        Debug.Log(Str); 

        //修改p的所有字段值 
        Debug.Log("修改P1的值:   "); 
        p1.Name = "test000222222";  
        p1.Age = 100;  
        p1.Job.JobName = "Manager";  
        p1.Job.ID = 1111;  

        Str = string.Format("修改后:p.Name={0},p.Age={1},p.Job.JobName={2}", p.Name, p.Age, p.Job.JobName);  
        Debug.Log(Str); 
        Str = string.Format("修改后:p1.Name={0},p1.Age={1},p1.Job.JobName={2}", p1.Name, p1.Age, p1.Job.JobName);  
        Debug.Log(Str); 
        Str = string.Format("修改后:p2.Name={0},p2.Age={1},p2.Job.JobName={2}", p2.Name, p2.Age, p2.Job.JobName); 
        Debug.Log(Str); 
    }
}

結果輸出:

  

結論:

  這個結果可以看出,淺表副本和原始副本並不是一個對象,但是,淺表副本復制了原始對象的值類型和string類型,但是數組只復制了引用。

      這個現象很有趣,按照MSDN的定義:“MemberwiseClone 方法創建一個淺表副本,方法是創建一個新對象,然后將當前對象的非靜態字段復制到該新對象。

      如果字段是值類型的,則對該字段執行逐位復制。如果字段是引用類型,則復制引用但不復制引用的對象;因此,原始對象及其復本引用同一對象。”,

  但是,在實際上,string應該也是引用類型,但是,淺表副本卻復制了這個值。

  無論是淺拷貝與深拷貝,C#都將源對象中的所有字段復制到新的對象中。不過,對於值類型字段,引用類型字段以及字符串類型字段的處理,兩種拷貝方式存在一定的區別(見下表)。

  

參考: http://visionsky.blog.51cto.com/blog/733317/237917

    http://blog.csdn.net/yl2isoft/article/details/12200513


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM