c# 深拷贝与浅拷贝/深克隆与浅克隆
首先描述一下拷贝的含义:拷贝就类似与复制,是为对象创建副本的技术。
c#中的拷贝分为深拷贝和浅拷贝。
浅拷贝:主要分为两种情况来讨论:值类型和引用类型。对于值类型来说:浅拷贝,拷贝的是对象的值。对于引用类型来说:拷贝的是对象的引用地址。
一般情况下都建议继成ICloneable,显示表明类型可以拷贝,具体如下:
public class TestClone : ICloneable { public int test { set; get; } public object Clone() { return this.MemberwiseClone(); } }
深拷贝:无论值类型还是引用类型,都是拷贝的对象的值。
深拷贝的实现方式:对于值类型来说,浅拷贝即是深拷贝。但是对于引用类型来说不一样,所以我们这里讨论的实现方式是对引用类型来说的。一般可以使用序列化,或者自定义方法,对每个对象进行复制。
注意:我们在浅拷贝时,对引用类型来说,拷贝的对象的引用,即旧对象的值改变,新对象的值也会改变,相反,新对象的值改变,旧对象的值也会改变。例如如下代码:
public class TestClone : ICloneable { public string IDCard { set; get; } public bool testBool { set; get; } public List<int> testList { set; get; } public int test { set; get; } public object Clone() { return this.MemberwiseClone(); } } static void Main(string[] args) { TestClone cloneOld = new TestClone(); cloneOld.test = 1; cloneOld.testList = new List<int> { 1, 2 }; cloneOld.testBool = true; TestClone cloneNew = (TestClone)cloneOld.Clone(); Console.WriteLine(cloneOld.test); Console.WriteLine(cloneNew.test); Console.WriteLine(cloneOld.testList.Count); Console.WriteLine(cloneNew.testList.Count); Console.WriteLine(cloneOld.testBool); Console.WriteLine(cloneNew.testBool); Console.WriteLine("改变old的值"); cloneOld.test = 100; cloneOld.testList = new List<int> { 1, 2 ,3,4,5}; cloneOld.testBool = false; Console.WriteLine(cloneOld.test); Console.WriteLine(cloneNew.test); Console.WriteLine(cloneOld.testList.Count); Console.WriteLine(cloneOld.testList.Count); Console.WriteLine(cloneOld.testBool); Console.WriteLine(cloneNew.testBool); }
运行结果如下:
从以上结果可以看出:
引用类型中的值类型在浅拷贝时,是拷贝的是对象的值。
引用类型在浅拷贝时,拷贝的是对象的引用。
string类型的引用类型较为特殊,当浅拷贝时,是将对应的而引用拷贝给了新的对象,但是当旧对象的值发生改变时,新对象的值并不发生改变,因为在每次改变string的值是,都会创建一个新的string对象。即一旦创建了该string对象,就不能修改此对象的值了。