如何克隆对象
当我做以下事情..任何做的人b修改人(我认为这样做会从人a克隆人b)。 我也不知道如果更改Person a会在链接后改变Person b。 由于我现在的代码,我只能看到这一个方向。
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;
有没有一种方法来完成这个任务?
不,不是。 你需要创build一个新的实例,以避免原来的影响“复制”。 这有几个选项:
-
如果你的types是一个
struct
,而不是一个class
,它将被值复制(而不是只复制引用到实例)。 这会给你所描述的语义,但有许多其他的副作用往往是不理想的,不build议任何可变types(这显然是,或这不会是一个问题!) -
在你的types上实现一个“克隆”机制。 这可以是
ICloneable
,甚至只是一个构造函数,它需要一个实例并从中复制值。 -
使用reflection,MemberwiseClone或类似的复制所有的值,所以你不必编写代码来做到这一点。 这有潜在的问题,特别是如果你有包含非简单types的字段。
你在找什么是克隆。 你将需要实施IClonable然后做克隆。
例:
class Person() : ICloneable { public string head; public string feet; #region ICloneable Members public object Clone() { return this.MemberwiseClone(); } #endregion }
那么你可以简单地调用Clone方法来做一个ShallowCopy (在这个特殊情况下也是一个DeepCopy )
Person a = new Person() { head = "big", feet = "small" }; Person b = (Person) a.Clone();
您可以使用Object类的MemberwiseClone方法来执行克隆。
我为此使用AutoMapper。 它是这样工作的:
Mapper.CreateMap(typeof(Person), typeof(Person)); Mapper.Map(a, b);
现在人a有人的所有属性b。
另外,AutoMapper也适用于不同的对象。 有关更多信息,请访问http://automapper.org
更新:我现在使用这个语法(简单地说 – 实际上CreateMaps在AutoMapperconfiguration文件中):
Mapper.CreateMap<Person, Person>; Mapper.Map(a, b);
请注意,您不必执行CreateMap来将同一types的一个对象映射到另一个对象,但是如果不这样做,AutoMapper将创build一个浅拷贝,意思是说,如果您更改一个对象,另一个也在变化。
克隆你的类对象可以使用Object.MemberwiseClone方法,
只需将这个函数添加到你的类中:
public class yourClass { // ... // ... public yourClass DeepCopy() { yourClass othercopy = (yourClass)this.MemberwiseClone(); return othercopy; } }
然后执行深度独立副本,只需调用DeepCopy方法即可:
yourClass newLine = oldLine.DeepCopy();
希望这可以帮助。
a
和b
只是对同一个Person对象的两个引用。 他们都基本上持有人的地址。
有一个ICloneable接口,虽然相对较less的类支持它。 有了这个,你会写:
Person b = a.Clone();
那么,b将是一个完全独立的Person
。
你也可以实现一个拷贝构造函数:
public Person(Person src) { // ... }
没有内置的方法来复制所有的字段。 你可以通过思考来做到这一点,但是会有性能的损失。
由于MemberwiseClone()方法不公开,我创build了这个简单的扩展方法,以便更容易地克隆对象:
public static T Clone<T>(this T obj) { var inst = obj.GetType().GetMethod("MemberwiseClone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); return (T)inst?.Invoke(obj, null); }
用法:
var clone = myObject.Clone();
public static T Clone<T>(T obj) { DataContractSerializer dcSer = new DataContractSerializer(obj.GetType()); MemoryStream memoryStream = new MemoryStream(); dcSer.WriteObject(memoryStream, obj); memoryStream.Position = 0; T newObject = (T)dcSer.ReadObject(memoryStream); return newObject; }
你可以这样做:
var jss = new JavaScriptSerializer(); var b = jss.Deserialize<Person>(jss.Serialize(a));
对于深度克隆你可能想看看这个答案: https : //stackoverflow.com/a/78612/550975
无痛:使用NClone库
Person a = new Person() { head = "big", feet = "small" }; Person b = Clone.ObjectGraph(a);
发生这种情况是因为“Person”是一个类,所以通过引用传递。 在语句“b = a”中,您只是复制对使用关键字new创build的唯一的“Person”实例的引用。
具有您正在查找的行为的最简单方法是使用“值types”。
只要更改来自人的声明
class Person
至
struct Person