C# 复制对象并在不更改原件的情况下使用复制件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9233046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Duplicate Object and working with Duplicate without changing Original
提问by Gotcha
Assuming I have an Object ItemVO in which there a bunch of properties already assigned. eg:
假设我有一个对象 ItemVO,其中已经分配了一堆属性。例如:
ItemVO originalItemVO = new ItemVO();
originalItemVO.ItemId = 1;
originalItemVO.ItemCategory = "ORIGINAL";
I would like to create another duplicate by using :
我想使用以下方法创建另一个副本:
duplicateItemVO = originalItemVO;
and then use the duplicateItemVO and alter its' properties, WITHOUT changing the originalItemVO:
然后使用duplicateItemVO并更改其属性,而不更改原始ItemVO:
// This also change the originalItemVO.ItemCategory which I do not want.
duplicateItemVO.ItemCategory = "DUPLICATE"
How can I achieve this, without changing the class ItemVO ?
如何在不更改 ItemVO 类的情况下实现这一点?
Thanks
谢谢
public class ItemVO
{
public ItemVO()
{
ItemId = "";
ItemCategory = "";
}
public string ItemId { get; set; }
public string ItemCategory { get; set; }
}
回答by Reed Copsey
You would need to construct a new instance of your class, not just assign the variable:
您需要构造类的新实例,而不仅仅是分配变量:
duplicateItemVO = new ItemVO
{
ItemId = originalItemVO.ItemId,
ItemCategory = originalItemVO.ItemCategory
};
When you're dealing with reference types (any class), just assigning a variable is creating a copy of the reference to the original object. As such, setting property values within that object will change the original as well. In order to prevent this, you need to actually construct a new object instance.
当您处理引用类型(任何类)时,仅分配一个变量就是创建对原始对象的引用的副本。因此,在该对象中设置属性值也会更改原始值。为了防止这种情况,您需要实际构造一个新的对象实例。
回答by Chamika Sandamal
class are reference typeand when you change one instance it will change the ariginal refference. so use value typeobject for overcome your task(ex: use structinstead of class)
class 是引用类型,当您更改一个实例时,它将更改原始引用。所以使用值类型对象来克服你的任务(例如:使用结构而不是类)
public struct ItemVO { *** }
or you can implement ICloneable Interfacefor your class
或者你可以为你的类实现 ICloneable 接口
回答by Sofian Hnaide
In order to change one instance without changing the other you need to clone the actual values of this instance and not the reference. The pattern used in .Net is to implement ICloneable. So your code would look like this:
为了在不更改另一个实例的情况下更改一个实例,您需要克隆该实例的实际值而不是引用。.Net 中使用的模式是实现 ICloneable。所以你的代码看起来像这样:
public class ItemVO: ICloneable
{
public ItemVO()
{
ItemId = "";
ItemCategory = "";
}
public string ItemId { get; set; }
public string ItemCategory { get; set; }
public object Clone()
{
return new ItemVO
{
ItemId = this.ItemId,
ItemCategory = this.ItemCategory
};
}
}
Now notice that you need an explicit cast when using Clone() (or you can make your own that returns ItemVO).
现在请注意,在使用 Clone() 时需要显式转换(或者您可以创建自己的返回 ItemVO 的转换)。
duplicateItemVO = (ItemVO) originalItemVO.Clone();
回答by Partha Ranjan
By Default objects are reference type.
默认对象是引用类型。
Assign the one object to another object its means that you just refer the address of the object.Any changes in any object it will reflect in both.
将一个对象分配给另一个对象,这意味着您只需引用该对象的地址。任何对象中的任何更改都将反映在两者中。
To solve this problem you should have initialize the object using "new" keyword, then add this object value in the first object.
要解决此问题,您应该使用“new”关键字初始化对象,然后将此对象值添加到第一个对象中。
回答by Venugopal M
You cannot practically copy an object since they would more likely be of reference types. The ideal method is to serialize or stream the object into a new one - Provided your class is serializable (by providing the [Serializable] attribute in class declaration).
您实际上无法复制对象,因为它们更可能是引用类型。理想的方法是将对象序列化或流式传输到一个新对象中 - 前提是您的类是可序列化的(通过在类声明中提供 [Serializable] 属性)。
private static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
Now you can use this code:
现在您可以使用此代码:
[Serializable]
public class MyClass
{
public int a {get; set;}
public int b {get; set;}
}
var obj = new MyClass{
a = 10,
b = 20,
};
var newobj = Clone<MyClass>(obj);
You will get an entirely new copy of obj. Note: Any other class inside MyClass must also be declared with the attribute [Serializable].
您将获得 obj 的全新副本。注意:MyClass 中的任何其他类也必须使用 [Serializable] 属性进行声明。
回答by Jamie Pearcey
As of c# 4.5 the base class object contains a method called MemberwiseClone that enables you to perform a shallow copy of that object and returns the result as a new instance. (If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.)
从 c# 4.5 开始,基类对象包含一个名为 MemberwiseClone 的方法,该方法使您能够执行该对象的浅拷贝并将结果作为新实例返回。(如果字段是值类型,则执行字段的逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其克隆引用到同一个对象。)
This is useful if you are looking to implement a prototype design pattern.
如果您希望实现原型设计模式,这将非常有用。
If you are looking to implement a deep copy (everything within the class is duplicated as new instances) then serialization or reflection are probably the best tools
如果您希望实现深度复制(类中的所有内容都复制为新实例),那么序列化或反射可能是最好的工具
回答by Luiz Bai?o
I suggest using as is in the link below. For me it worked very well.
我建议在下面的链接中按原样使用。对我来说,它工作得很好。
https://msdn.microsoft.com/en-us/library/system.object.memberwiseclone(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.object.memberwiseclone(v=vs.110).aspx
public Person ShallowCopy ()
{
return (Person) this.MemberwiseClone ();
}
回答by Amit
To duplicate an object by value instead of reference, you can serialize it (e.g. JSON) and then deserialize it right after. You then have a copy by value.
要按值而不是引用复制对象,您可以序列化它(例如 JSON),然后立即反序列化它。然后你有一个按值的副本。
Here's an example
这是一个例子
ItemVO originalItemVO = new ItemVO();
originalItemVO.ItemId = 1;
originalItemVO.ItemCategory = "ORIGINAL";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(originalItemVO);
ItemVO duplicateItemVO = Newtonsoft.Json.JsonConvert.DeserializeObject<ItemVO>(json);

