在 C# 中像 CopyTo 一样实现 memcpy() 的简单方法

发布于 2024-08-16 05:31:13 字数 294 浏览 5 评论 0原文

是否有一种“简单”的方法来实现像 CopyTo()MemberwiseCopy (而不是 Clone()MemberwiseClone代码>) 在 C# 中?我不想创建一个新对象,因为我希望每个持有旧对象的人都能够看到新对象的属性,这可能完全不同。虽然其中大多数派生自可以包含某些抽象函数的父类,但我不想编写几百行代码来逐一复制每个成员。可能需要全部复制(糟糕的设计,但它不是我的,也没有被重写)。看来微软会为此创建一个界面,还是我大大错过了一些东西?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我认为序列化/反序列化是执行此操作的“最简单”方法。此外,还有一种更快的方法,即使用固定手柄。

你可以使用 Marshal & GCHandle 像这样(来自此链接):

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; 
} 

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; 
} 
夜吻♂芭芘 2024-08-23 05:31:13

我不明白这个问题。听起来您只想创建对现有对象的引用。

C# 中对象的变量仅保存对该对象的引用,因此当您将变量分配给现有对象时,您仍然在访问同一个对象。

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

对于上面的代码,y.MyProperty==“hello”也是如此。

您是否正在尝试获取深层副本,即每个具有引用类型的字段也被设置为原始引用对象的 MemberwiseClone() ,无限循环?

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?

泅渡 2024-08-23 05:31:13

您可以使用序列化到内存流并反序列化回实例。

我们的项目中有这样一个“DeepCopy”方法。这有点冒险。我们开始在我们的类中实现复制属性方法或复制构造函数,因为它更可靠并且最终提供更多控制。

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.

我的黑色迷你裙 2024-08-23 05:31:13

如果您想用另一个实例的值覆盖对象的所有现有字段,则没有简单的方法可以做到这一点。如果您愿意编写一些古怪的反射代码来访问对象的每个字段并复制值,这是可以完成的。但它会变得脆弱和混乱。

此外,为了正确执行此操作,您需要遍历对象的继承树并执行相同的赋值操作。

最后,如果对象包含 readonly 字段,则可能无法复制另一个实例的确切状态,并且您将被迫决定不一致的副本是否是可接受的复制结果。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文