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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值