在C#中实施CopyTo()
至MemberwiseCopy
(而不是Clone()
或MemberwiseClone
)的方式是否“简单”?我不想创建一个新对象,因为我希望每个拥有旧对象的人都能够看到新对象的属性,这可能是完全不同的。虽然大多数这些派生自一个可以保留一些抽象函数的父类,但我不想写几百行代码只是为了逐个复制每个成员。可能需要复制所有这些(糟糕的设计,但它不是我的,也不是被重写)。看起来微软会为此创建一个界面,还是我错过了什么?
答案 0 :(得分:5)
我不明白这个问题。听起来你只想创建对现有对象的引用。
C#中对象的变量只包含对象的引用,因此当您将变量赋值给现有对象时,您仍然可以访问同一个对象。
Object x = new Object();
Object y = x;
x.MyProperty = "hello";
对于上面的代码,y.MyProperty ==“hello”。
您是否正在尝试获取深层副本,即每个具有引用类型的字段也设置为原始引用对象的MemberwiseClone(),无限制?
答案 1 :(得分:3)
我认为序列化/反序列化是“最简单”的方法。另外,使用固定手柄可以更快地完成它。
你可以使用Marshal&像这样的GCHandle(来自this link):
public static object RawDeserializeEx( byte[] rawdatas, Type anytype )
{
int rawsize = Marshal.SizeOf( anytype );
if( rawsize > rawdatas.Length )
return null;
GCHandle handle = GCHandle.Alloc( rawdatas, GCHandleType.Pinned );
IntPtr buffer = handle.AddrOfPinnedObject();
object retobj = Marshal.PtrToStructure( buffer, anytype );
handle.Free();
return retobj;
}
public static byte[] RawSerializeEx( object anything )
{
int rawsize = Marshal.SizeOf( anything );
byte[] rawdatas = new byte[ rawsize ];
GCHandle handle = GCHandle.Alloc( rawdatas, GCHandleType.Pinned );
IntPtr buffer = handle.AddrOfPinnedObject();
Marshal.StructureToPtr( anything, buffer, false );
handle.Free();
return rawdatas;
}
答案 2 :(得分:2)
您可以将序列化用于内存流并反序列化回实例。
我们的项目中有这样一个“DeepCopy”方法。这有点危险。我们开始实现copy-property-methods或将构造函数复制到我们的类中,因为它更可靠并且在最后提供更多控制。
答案 3 :(得分:0)
如果要使用其他实例中的值覆盖对象的所有现有字段,则没有 easy 方法可以执行此操作。如果您愿意编写一些古怪的反射代码来访问对象的每个字段并复制值,则可以执行此操作。但它会很脆弱而且很混乱。
此外,要正确执行此操作,您还需要遍历对象的继承树并执行相同的赋值操作。
最后,如果对象包含readonly
字段,则可能无法复制另一个实例的确切状态,并且您将被迫决定不一致的副本是否是该副本的可接受结果。