C#对象复制 ICloneable

时间:2023-03-09 08:35:41
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(, 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 = ,Job = new Job(){JobName="Coder",ID = } }; 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 = ;
p1.Job.JobName = "Manager";
p1.Job.ID = ; 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);
}
}

结果输出:

 C#对象复制 ICloneable 

结论:

  这个结果可以看出,浅表副本和原始副本并不是一个对象,但是,浅表副本复制了原始对象的值类型和string类型,但是数组只复制了引用。

这个现象很有趣,按照MSDN的定义:“MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。

如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。”,

  但是,在实际上,string应该也是引用类型,但是,浅表副本却复制了这个值。

  无论是浅拷贝与深拷贝,C#都将源对象中的所有字段复制到新的对象中。不过,对于值类型字段,引用类型字段以及字符串类型字段的处理,两种拷贝方式存在一定的区别(见下表)。

  C#对象复制 ICloneable

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

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