在c#中创建对象的副本
本文关键字:副本 创建对象 | 更新日期: 2023-09-27 18:01:20
请看下面的代码(摘自一本c#书籍):
public class MyClass
{
public int val;
}
public struct myStruct
{
public int val;
}
public class Program
{
private static void Main(string[] args)
{
MyClass objectA = new MyClass();
MyClass objectB = objectA;
objectA.val = 10;
objectB.val = 20;
myStruct structA = new myStruct();
myStruct structB = structA;
structA.val = 30;
structB.val = 40;
Console.WriteLine("objectA.val = {0}", objectA.val);
Console.WriteLine("objectB.val = {0}", objectB.val);
Console.WriteLine("structA.val = {0}", structA.val);
Console.WriteLine("structB.val = {0}", structB.val);
Console.ReadKey();
}
}
我理解它产生如下输出:
objectA.val = 20
objectB.val = 20
structA.val = 30
structB.val = 40
输出的最后两行我没有问题,但前两行告诉我objectA
和objectB
指向同一个内存块(因为在c#中,对象是引用类型)。
问题是如何使objectB
, objectA
的副本,使其指向内存中的不同区域。我理解尝试分配它们的成员可能不起作用,因为这些成员也可能是引用。那么我该如何使objectB
成为与objectA
完全不同的实体呢?
你可以这样做:
class myClass : ICloneable
{
public String test;
public object Clone()
{
return this.MemberwiseClone();
}
}
那么你可以做
myClass a = new myClass();
myClass b = (myClass)a.Clone();
注意:MemberwiseClone()
创建当前System.Object的浅拷贝
没有内置的方法。您可以让MyClass实现IClonable
接口(但它有点过时),或者只是编写自己的Copy/Clone方法。无论哪种情况,您都必须编写一些代码。
对于大对象,你可以考虑序列化+反序列化(通过MemoryStream),只是为了重用现有的代码。
无论采用何种方法,请仔细考虑"副本"的确切含义。应该有多深,Id字段是否例外等等
最简单的方法是在MyClass类中编写一个复制构造函数。
像这样:
namespace Example
{
class MyClass
{
public int val;
public MyClass()
{
}
public MyClass(MyClass other)
{
val = other.val;
}
}
}
第二个构造函数只是接受他自己类型的形参(你想复制的那个),并创建一个赋值相同的新对象
class Program
{
static void Main(string[] args)
{
MyClass objectA = new MyClass();
MyClass objectB = new MyClass(objectA);
objectA.val = 10;
objectB.val = 20;
Console.WriteLine("objectA.val = {0}", objectA.val);
Console.WriteLine("objectB.val = {0}", objectB.val);
Console.ReadKey();
}
}
输出:objectA.val = 10
objectB.val = 20
这里已经有一个问题了,你可以读一读
深度克隆对象
没有Clone()方法,例如,它存在于Java中,但您可以在类中包含复制构造函数,这是另一种好方法。
class A
{
private int attr
public int Attr
{
get { return attr; }
set { attr = value }
}
public A()
{
}
public A(A p)
{
this.attr = p.Attr;
}
}
这是一个示例,在构建新对象时复制成员'Attr'。