如何克隆对象
当我执行以下操作时......对人 b 所做的任何操作都会修改人 a (我认为这样做会从人 a 克隆人 b)。我也不知道链接后更改人员 a 是否会更改人员 b。由于我现在的代码,我只能在 1 个方向看到这一点。
Person a = new Person() { head = "big", feet = "small" };
Person b = a;
b.head = "small"; //now a.head = "small" too
现在,如果我这样做……a 就变得完全独立了。
Person b = new Person() { head = a.head, feet = a.feet };
现在,将此行为与 C# 中的其他行为进行比较时,这很好,而且有点有意义。但是,这对于大型物体来说可能会变得非常烦人。
有没有办法缩短这个时间呢?
如:
Person b = a.Values;
When I do the following.. anything done to Person b modifies Person a (I thought doing this would clone Person b from Person a). I also have NO idea if changing Person a will change Person b after the linking. Due to my code right now, I can only see this in 1 direction.
Person a = new Person() { head = "big", feet = "small" };
Person b = a;
b.head = "small"; //now a.head = "small" too
Now if I do this instead.. Person a becomes completely separate.
Person b = new Person() { head = a.head, feet = a.feet };
Now this fine and kinda makes sense when comparing this behaviour to other things in C#. BUT, this could get very annoying with large objects.
Is there a way to shortcut this at all?
Such as:
Person b = a.Values;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
您正在寻找的是克隆。您需要实现IClonable,然后进行克隆。
示例:
然后您可以简单地调用 Clone 方法来执行ShallowCopy(在这种特殊情况下也可以DeepCopy)
您可以使用MemberwiseClone Object 类的方法来执行克隆。
What you are looking is for a Cloning. You will need to Implement IClonable and then do the Cloning.
Example:
Then You can simply call the Clone method to do a ShallowCopy (In this particular Case also a DeepCopy)
You can use the MemberwiseClone method of the Object class to do the cloning.
不,不是真的。您需要创建一个新实例,以避免原始实例影响“副本”。有几个选项可以实现此目的:
如果您的类型是
struct
,而不是class
,它将按值复制(而不是仅复制引用)到实例)。这将为它提供您所描述的语义,但会产生许多其他副作用,这些副作用往往不太理想,并且不建议用于任何可变类型(这显然是,否则这不会成为问题!)< /p>ICloneable
,甚至只是一个获取实例并从中复制值的构造函数。使用反射、MemberwiseClone 或类似方法来复制所有值,因此您无需编写代码来执行此操作。这存在潜在的问题,特别是当您的字段包含非简单类型时。
No, not really. You'll need to make a new instance in order to avoid the original from affecting the "copy". There are a couple of options for this:
If your type is a
struct
, not aclass
, it will be copied by value (instead of just copying the reference to the instance). This will give it the semantics you're describing, but has many other side effects that tend to be less than desirable, and is not recommended for any mutable type (which this obviously is, or this wouldn't be an issue!)Implement a "cloning" mechanism on your types. This can be
ICloneable
or even just a constructor that takes an instance and copies values from it.Use reflection, MemberwiseClone, or similar to copy all values across, so you don't have to write the code to do this. This has potential problems, especially if you have fields containing non-simple types.
我为此使用 AutoMapper。它的工作原理是这样的:
现在,a 拥有 b 的所有属性。
顺便说一句,AutoMapper 也适用于不同的对象。有关更多信息,请访问 http://automapper.org
更新:我现在使用此语法(简单地说 - 实际上CreateMaps 在 AutoMapper 配置文件中):
请注意,您不必执行 CreateMap 将同一类型的一个对象映射到另一个对象,但如果不这样做,AutoMapper 将创建一个浅表副本,这对于外行来说意味着,如果你改变一个对象,另一个对象也会改变。
I use AutoMapper for this. It works like this:
Now person a has all the properties of person b.
As an aside, AutoMapper works for differing objects as well. For more information, check it out at http://automapper.org
Update: I use this syntax now (simplistically - really the CreateMaps are in AutoMapper profiles):
Note that you don't have to do a CreateMap to map one object of the same type to another, but if you don't, AutoMapper will create a shallow copy, meaning to the lay man that if you change one object, the other changes also.
由于 MemberwiseClone() 方法不是公共的,因此我创建了这个简单的扩展方法,以便更轻松地克隆对象:
用法:
Since the MemberwiseClone() method is not public, I created this simple extension method in order to make it easier to clone objects:
Usage:
它再简单不过了:
只需将任何对象序列化为 JSON 字符串,然后反序列化即可。这将进行深度复制......
It couldn't be simpler than this:
Just serialize any object to a JSON string and then deserialize it. This will do a deep copy...
要克隆类对象,您可以使用 Object.MemberwiseClone 方法,
只需将此函数添加到您的类中:
然后要执行深度独立复制,只需调用 DeepCopy 方法:
To clone your class object you can use the Object.MemberwiseClone method,
just add this function to your class :
then to perform a deep independent copy, just call the DeepCopy method:
a
和b
只是对同一 Person 对象的两个引用。它们本质上都保存着Person
的地址。有一个 ICloneable 接口,尽管支持它的类相对较少。这样,您可以这样写:
那么,b 将是一个完全独立的
Person
。您还可以实现复制构造函数:
没有内置方法可以复制所有字段。您可以通过反射来做到这一点,但会降低性能。
a
andb
are just two references to the same Person object. They both essentially hold the address of thePerson
.There is a ICloneable interface, though relatively few classes support it. With this, you would write:
Then, b would be an entirely separate
Person
.You could also implement a copy constructor:
There is no built-in way to copy all the fields. You can do it through reflection, but there would be a performance penalty.
你可以这样做:
对于深度克隆,你可能想看看这个答案:
https://stackoverflow.com/a/78612/550975
You could do it like this:
For deep cloning you may want to take a look at this answer:
https://stackoverflow.com/a/78612/550975
正如其他人所建议的那样,
MemberwiseClone
是进行浅复制的好方法。然而它是受保护的,所以如果你想在不改变类的情况下使用它,你必须通过反射来访问它。然而反射速度很慢。因此,如果您计划克隆大量对象,则可能值得缓存结果:您可以这样调用它:
MemberwiseClone
is a good way to do a shallow copy as others have suggested. It is protected however, so if you want to use it without changing the class, you have to access it via reflection. Reflection however is slow. So if you are planning to clone a lot of objects it might be worthwhile to cache the result:You can call it like this:
无痛:使用 NClone 库
Painlessly: Using NClone library
与 @ChtiouiMalek 的答案类似,但使用
System.Text.Json
您可以序列化和反序列化以获得对象的深层克隆,例如,当然,您可以将其作为 1-liner 来执行:
Similar to @ChtiouiMalek's answer but with
System.Text.Json
you can serialize and deserialize to get a deep clone of your object, e.g.And, of course, you can do it as a 1-liner:
在我看来,最好的方法是实现您自己的
Clone()
方法,如下所示。输出:
b
完全独立于a
,因为它不是引用,而是克隆。希望我能帮忙!
In my opinion, the best way to do this is by implementing your own
Clone()
method as shown below.Output:
b
is totally independent toa
, due to it not being a reference, but a clone.Hope I could help!
这段代码对我有用。它还需要很少的时间来执行。
This code worked for me. It also takes a very small amount of time to execute.
这就是我使用内置 Json 类解决它并创建一些扩展方法的方法。这些扩展方法在我的整个项目中都很有用。 (这是在 .NET 6 上运行的)
This is how I have solved it using the built in Json class and created some extension methods. These extension methods come in handy all over my project. (This is running on .NET 6)
发生这种情况是因为“Person”是一个类,因此它是通过引用传递的。
在语句“b = a”中,您只是复制对使用关键字 new 创建的唯一“Person”实例的引用。
获得您正在寻找的行为的最简单方法是使用“值类型”。
只需将 Person 声明从 更改
为
This happens because "Person" is a class, so it is passed by reference.
In the statement "b = a" you are just copying a reference to the one and only "Person" instance that you created with the keyword new.
The easiest way to have the behavior that you are looking for is to use a "value type".
Just change the Person declaration from
to