转自:http://www.cnblogs.com/jackal/archive/2011/04/29/2032613.html
深复制(deep copy)和浅复制(shallow copy)都是用于对象之间的拷贝。 注:参考CodeProject
浅复制:
创建一个新对象, 然后将当前对象的非静态字段拷贝到新对象.
如果字段是值类型的, 在堆栈上开辟一个新的空间, 将该字段进行逐位复制到新空间.
如果字段是引用类型的, 在堆栈区域开辟一个存放引用的空间, 将当前对象的引用复制到此空间, 而引用的对象不变. 因此, 原始对象及其复本引用同一对象。
在C#中创建一个浅表副本, 也就是克隆一个新的对象 使用MemberwiseClone()方法,返回一个当前对象的浅表副本。
下面是一个示例:
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class
ShallowCopy
{
public static string CompanyName = " My Company " ;
public int Age;
public string EmployeeName;
public CLSRefSalary clsRefSalary ;
public ShallowCopy CreateShallowCopy(ShallowCopy inputShallowCopy)
{
return (ShallowCopy)inputShallowCopy.MemberwiseClone();
}
}
class CLSRefSalary
{
public CLSRefSalary( int _salary)
{
Salary = _salary;
}
public int Salary;
}
{
public static string CompanyName = " My Company " ;
public int Age;
public string EmployeeName;
public CLSRefSalary clsRefSalary ;
public ShallowCopy CreateShallowCopy(ShallowCopy inputShallowCopy)
{
return (ShallowCopy)inputShallowCopy.MemberwiseClone();
}
}
class CLSRefSalary
{
public CLSRefSalary( int _salary)
{
Salary = _salary;
}
public int Salary;
}
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class
Program
{
static void Main( string [] args)
{
// 创建一个ShallowCopy的实例shallowCopy
ShallowCopy shallowCopy = new ShallowCopy();
shallowCopy.Age = 25 ;
shallowCopy.EmployeeName = " Ahmed Eid " ;
// 创建一个CLSRefSalary实例,并赋值给shallowCopy对象的clsRefSalary
CLSRefSalary clsRefSalary = new CLSRefSalary( 1000 );
shallowCopy.clsRefSalary = clsRefSalary;
// 创建一个ShallowCopy的浅副本shallowCopy2
ShallowCopy shallowCopy2 = shallowCopy.CreateShallowCopy(shallowCopy);
// 改变shallowCopy2中引用对象clsRefSalary里字段Salary的值
shallowCopy2.clsRefSalary.Salary = 2000 ;
// 检查原对象shallowCopy中引用对象clsRefSalary的值,结果EmpSalary=2000
// 所以浅复制只是拷贝了引用类型在堆栈区域的引用, 而没有拷贝引用类型在托管堆上的对象,原引用和拷贝后的引用都是指向托管堆的同一个位置
int EmpSalary = shallowCopy.clsRefSalary.Salary;
}
}
{
static void Main( string [] args)
{
// 创建一个ShallowCopy的实例shallowCopy
ShallowCopy shallowCopy = new ShallowCopy();
shallowCopy.Age = 25 ;
shallowCopy.EmployeeName = " Ahmed Eid " ;
// 创建一个CLSRefSalary实例,并赋值给shallowCopy对象的clsRefSalary
CLSRefSalary clsRefSalary = new CLSRefSalary( 1000 );
shallowCopy.clsRefSalary = clsRefSalary;
// 创建一个ShallowCopy的浅副本shallowCopy2
ShallowCopy shallowCopy2 = shallowCopy.CreateShallowCopy(shallowCopy);
// 改变shallowCopy2中引用对象clsRefSalary里字段Salary的值
shallowCopy2.clsRefSalary.Salary = 2000 ;
// 检查原对象shallowCopy中引用对象clsRefSalary的值,结果EmpSalary=2000
// 所以浅复制只是拷贝了引用类型在堆栈区域的引用, 而没有拷贝引用类型在托管堆上的对象,原引用和拷贝后的引用都是指向托管堆的同一个位置
int EmpSalary = shallowCopy.clsRefSalary.Salary;
}
}
深复制
对于值类型深复制与浅复制相同.
对于引用类型,分别在堆栈和托管堆上开辟新的空间,将原引用对象的引用和引用的对象复制到堆栈和托管堆上.
如果要克隆一个类,则这个类必须要标记为可序列化的([Serializable])
示例:
这个实例没有去实现ICloneable接口, 也没实现里面的Clone()方法,而是自定义一个Clone()方法;
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
[Serializable]
class DeepCopy
{
public static string CompanyName = " My Company " ;
public int Age;
public string EmployeeName;
public CLSRefSalary clsRefSalary;
public DeepCopy CreateDeepCopy(DeepCopy inputDeepCopy)
{
MemoryStream m = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
b.Serialize(m, inputDeepCopy);
m.Position = 0 ;
return (DeepCopy)b.Deserialize(m);
}
}
[Serializable]
class CLSRefSalary
{
public CLSRefSalary( int _salary)
{
Salary = _salary;
}
public int Salary;
}
class DeepCopy
{
public static string CompanyName = " My Company " ;
public int Age;
public string EmployeeName;
public CLSRefSalary clsRefSalary;
public DeepCopy CreateDeepCopy(DeepCopy inputDeepCopy)
{
MemoryStream m = new MemoryStream();
BinaryFormatter b = new BinaryFormatter();
b.Serialize(m, inputDeepCopy);
m.Position = 0 ;
return (DeepCopy)b.Deserialize(m);
}
}
[Serializable]
class CLSRefSalary
{
public CLSRefSalary( int _salary)
{
Salary = _salary;
}
public int Salary;
}
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
class
Program
{
static void Main( string [] args)
{
// 创建一个DeepCopy实例
DeepCopy deepCopy = new DeepCopy();
deepCopy.Age = 25 ;
deepCopy.EmployeeName = " Ahmed Eid " ;
// 创建CLSRefSalary实例,赋值给deepCopy对象的clsRefSalary
CLSRefSalary clsRefSalary = new CLSRefSalary( 1000 );
deepCopy.clsRefSalary = clsRefSalary;
// 创建一个DeepCopy的浅副本deepCopy2
DeepCopy deepCopy2 = deepCopy.CreateDeepCopy(deepCopy);
// 改变deepCopy2中引用对象clsRefSalary里字段Salary的值
deepCopy2.clsRefSalary.Salary = 2000 ;
// 检查原对象deepCopy中引用对象clsRefSalary的值,结果EmpSalary=1000
int EmpSalary = deepCopy.clsRefSalary.Salary;
}
}
{
static void Main( string [] args)
{
// 创建一个DeepCopy实例
DeepCopy deepCopy = new DeepCopy();
deepCopy.Age = 25 ;
deepCopy.EmployeeName = " Ahmed Eid " ;
// 创建CLSRefSalary实例,赋值给deepCopy对象的clsRefSalary
CLSRefSalary clsRefSalary = new CLSRefSalary( 1000 );
deepCopy.clsRefSalary = clsRefSalary;
// 创建一个DeepCopy的浅副本deepCopy2
DeepCopy deepCopy2 = deepCopy.CreateDeepCopy(deepCopy);
// 改变deepCopy2中引用对象clsRefSalary里字段Salary的值
deepCopy2.clsRefSalary.Salary = 2000 ;
// 检查原对象deepCopy中引用对象clsRefSalary的值,结果EmpSalary=1000
int EmpSalary = deepCopy.clsRefSalary.Salary;
}
}
对于CreateDeepCopy()可以用泛型实现一个通用的Clone()方法
public
static
T CreateDeepCopy
<
T
>
(T item)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, item);
stream.Seek( 0 , SeekOrigin.Begin);
T result = (T)formatter.Deserialize(stream);
stream.Close();
return result;
}
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, item);
stream.Seek( 0 , SeekOrigin.Begin);
T result = (T)formatter.Deserialize(stream);
stream.Close();
return result;
}