關於淺拷貝和深拷貝,我的理解不是很清晰,簡單說來,我認為是這樣子:
淺拷貝:引用成員在被拷貝時僅複製來源物件中引用成員的地址到新對象中,所以在新對象中對引用成員變更會影響到來源物件(除對引用成員進行賦值外)。
深拷貝:引用成員在拷貝時建立一個引用對象到新對象中,且將來源物件中引用對象的成員值複製到新對象的引用對象中,所以在新對象中對引用成員變更不會影響來源物件。
說起來概念也簡單,我想大家糾結的是如何?深拷貝?淺拷貝的實現很簡單,調用Object.MemberwiseClone就萬事大吉了。在網上找了一個通過序列化實現深拷貝的例子,自己改了改,歡迎大家品頭論足。
這段程式的輸出為:
objA1.RefClass.Field = 10
objA2.RefClass.Field = 10
objA1.RefClass.Field = 10
objA2.RefClass.Field = 30
objB1.RefClass.Field = 20
objB2.RefClass.Field = 10
要注意的是,本例中實現深拷貝的ClassB類及其引用成員RefClass類必須添加Serializable特性。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace ConsoleApplication1
{
//被引用類,必須添加Serializable特性,否則不能實現序列化
[Serializable]
class RefClass
{
private int field;
public int Field
{
get { return field; }
set { this.field = value; }
}
}
//淺拷貝樣本
class ClassA : ICloneable
{
private RefClass refClass;
public RefClass RefClass
{
get { return refClass; }
set { refClass = value; }
}
public ClassA()
{
refClass = new RefClass();
}
public object Clone()
{
//調用MemberwiseClone實現淺拷貝
return MemberwiseClone();
}
}
//深拷貝樣本,必須添加Serializable特性,否則不能實現序列化
[Serializable]
class ClassB : ICloneable
{
private RefClass refClass;
public RefClass RefClass
{
get { return refClass; }
}
public ClassB()
{
refClass = new RefClass();
}
//深拷貝
public object Clone()
{
//建立記憶體流
MemoryStream ms = new MemoryStream();
//以二進位格式進行序列化
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, this);
//還原序列化當前執行個體到一個object
ms.Seek(0, 0);
object obj = bf.Deserialize(ms);
//關閉記憶體流
ms.Close();
return obj;
}
}
class Program
{
static void Main(string[] args)
{
//淺拷貝
ClassA objA1 = new ClassA();
objA1.RefClass.Field = 20;
ClassA objA2 = (ClassA)objA1.Clone();
//在新對象中修改RefClass的Field值,來源物件中的值亦更改
objA2.RefClass.Field = 10;
Console.WriteLine("objA1.RefClass.Field = " + objA1.RefClass.Field.ToString());
Console.WriteLine("objA2.RefClass.Field = " + objA2.RefClass.Field.ToString());
//對新對象中的RefClass重新進行賦值操作,不影響來源物件
objA2.RefClass = new RefClass();
objA2.RefClass.Field = 30;
Console.WriteLine("objA1.RefClass.Field = " + objA1.RefClass.Field.ToString());
Console.WriteLine("objA2.RefClass.Field = " + objA2.RefClass.Field.ToString());
//深拷貝
ClassB objB1 = new ClassB();
objB1.RefClass.Field = 20;
ClassB objB2 = (ClassB)objB1.Clone();
//在新對象中修改RefClass的Field值,來源物件中的值不變
objB2.RefClass.Field = 10;
Console.WriteLine("objB1.RefClass.Field = " + objB1.RefClass.Field.ToString());
Console.WriteLine("objB2.RefClass.Field = " + objB2.RefClass.Field.ToString());
Console.ReadKey();
}
}
}