对象复制的浅与深

编程中,经常需要复制对象。有时,只是简单地让两个对象变量引用同一个对象,但有时需要两个独立的副本,以便在不影响原始对象的情况下修改数据。在.NET环境中,可以通过浅复制和深复制来实现这一需求。

浅复制与深复制

浅复制创建一个新的对象,并将原始对象的每个成员赋值给新对象的对应成员。对于值类型的成员,这是一种真正的复制;但对于包含引用类型的成员,这并不会产生真正的复制。例如,字符串(string)是一种引用类型。当将一个字符串变量赋值给另一个字符串变量时,两个变量都会引用相同的字符串数据。字符串的字符并没有真正被复制。因此,如果一个类包含引用成员,浅复制并不会产生所有类成员的真正副本。

在许多情况下,浅复制是足够的。需要注意的是,字符串是不可变的,不能被改变。当创建一个包含字符串的浅复制对象,并在新对象中修改字符串时,这将创建一个新的字符串,并且不会对原始对象中的原始字符串产生任何影响。需要注意的是,其他数据类型,如数组、类对象以及类对象数组,可能会比字符串更复杂。

深复制

深复制是创建一个不包含任何原始数据的副本。每个成员的真正副本被创建。对于值类型成员,深复制不需要做任何特殊处理。但对于引用数据类型,新对象必须引用数据的副本,而不是原始数据。

在.NET中实现对象复制的方法并不复杂。下面是一个示例,展示了如何使用一个名为MyClass的类对象进行浅复制和深复制。

protected class MyClass { public int i; public int j; public string message; } private void Test() { MyClass mc1 = new MyClass(); mc1.i = 5; mc1.j = 10; mc1.message = "Hello, World!"; MyClass mc2 = new MyClass(); mc2.i = mc1.i; mc2.j = mc1.j; mc2.message = mc1.message; }

在浅复制中,没有做任何特殊处理。只是将一个对象的每个成员赋值给另一个对象。对于值类型的成员,深复制使用相同的代码。然而,对于引用类型的成员,如字符串,代码必须创建字符串数据的副本。

protected class MyClass : ICloneable { public int i; public int j; public string message; public object Clone() { MyClass mc = new MyClass(); mc.i = i; mc.j = j; if (message != null) mc.message = String.Copy(message); return mc; } } private void Test() { MyClass mc1 = new MyClass(); mc1.i = 5; mc1.j = 10; mc1.message = "Hello, World!"; MyClass mc2 = (MyClass)mc1.Clone(); }

在深复制中,通过实现ICloneable接口并重写Clone方法来实现。这种方式的主要优点是它作为类的一部分实现,可以轻松地在应用程序的任何地方进行修改和调用。

.NET框架提供的工具

.NET框架提供了一些工具来帮助执行这些任务。例如,可以使用MemberwiseClone方法来执行浅复制。

protected class MyClass : ICloneable { public int i; public int j; public string message; public object Clone() { return MemberwiseClone(); } } private void Test() { MyClass mc1 = new MyClass(); mc1.i = 5; mc1.j = 10; mc1.message = "Hello, World!"; MyClass mc2 = (MyClass)mc1.Clone(); }

在这个示例中,使用MemberwiseClone方法来执行浅复制。MemberwiseClone方法是受保护的,因此不能直接从Test方法中调用。相反,修改了MyClass类,使其实现ICloneable接口,并实现了ICloneable的一个方法Clone。

protected class MyClass : ICloneable { public int i; public int j; public string message; public object Clone() { MyClass mc = new MyClass(); mc.i = i; mc.j = j; if (message != null) mc.message = String.Copy(message); return mc; } } private void Test() { MyClass mc1 = new MyClass(); mc1.i = 5; mc1.j = 10; mc1.message = "Hello, World!"; MyClass mc2 = (MyClass)mc1.Clone(); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485