tags:

views:

461

answers:

4

Is there an "easy" way to implement something like CopyTo() to MemberwiseCopy (instead of Clone() or MemberwiseClone) in C#? I don't want to create a new object, as I want everyone holding the old one to be able to see the attributes of the new one, which may be completely different. While most of these derive from a parent class which could hold some abstract function, I don't want to write a few hundred lines of code just to copy every member one by one. Which may need to be copied over all (bad design, but its not mine, nor is it being rewritten). It seems like Microsoft would have created an interface for this or have I greatly missed out on something?

+2  A: 

You could use serialization into a memory stream and deserialization back to an instance.

We have such a "DeepCopy" method in our project. It is kind of risky. We started to implement copy-property-methods or copy constructors into our classes because it is more reliable and gives more control at the end.

Stefan Steinegger
A: 

If you want to overwrite all of the existing fields of an object with the values from another instance, there is no easy way to do it. It can be done if you're willing to write some wacky reflection code to visit each field of the object and copy the values. But it would be fragile and messy.

Furthermore, to do it correctly, you would need to walk the inheritance tree of the object and perform the same assignment operations as well.

Finally, if the object contains readonly field, it may be impossible to copy the exact state of another instance, and you will be forced to decide whether inconsistent copies are an acceptable outcome of the copy.

LBushkin
If I'm correct, readonly has nothing to do with reflection.
deerchao
Readonly fields cannot be assigned to, even using reflection. This was the point I was trying to make. If you want to overwrite one object with the values from another one you will not be able to copy the values to readonly fields.
LBushkin
+5  A: 

I don't get the question. Sounds like you just want to create a reference to an existing object.

Variables to objects in C# merely hold a reference to the object, so when you assign a variable to an existing object, you're still accessing the same object.

Object x = new Object();
Object y = x;
x.MyProperty = "hello";

For the above code, y.MyProperty=="hello" as well.

Are you trying to get a deep copy, i.e., one where every field with a reference type is also set to a MemberwiseClone() of the originally-referenced object, ad infinitum?

richardtallent
+2  A: 

I think the serialization/deserialization is the "easiest" way to do this. Additionaly, there's a faster way to do it, using pinned handles.

You could use Marshal & GCHandle like such (from 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; 
}
Kel