深克隆对象 [英] Deep cloning objects
问题描述
我想做的事情是这样的:
I want to do something like:
myObject myObj = GetmyObj(); //Create and fill a new object
myObject newObj = myObj.Clone();
然后再进行更改,未反映在原始对象的新对象。
And then make changes to the new object that are not reflected in the original object.
我不经常需要此功能,所以当它是必要的,我已经使出创建一个新的对象,然后逐个复制每个属性,但它总是给我留下的感觉,那是一种更好或更优雅处理这种情况的方式。
I don't often need this functionality, so when it's been necessary, I've resorted to creating a new object and then copying each property individually, but it always leaves me with the feeling that there is a better or more elegant way of handling the situation.
我如何克隆或深复制一个对象,以使克隆的对象可以不作任何改变反映在原始对象?
How can I clone or deep copy an object so that the cloned object can be modified without any changes being reflected in the original object?
推荐答案
虽然标准的做法是实施的 ICloneable
接口(描述的此处,所以我不会反刍),这里是一个不错的深克隆对象复印机我发现<一href="http://www.$c$cproject.com/Articles/23832/Implementing-Deep-Cloning-via-Serializing-objects">The code计划前一阵子在我们的东西结合吧。
Whilst the standard practice is to implement the ICloneable
interface (described here, so I won't regurgitate), here's a nice deep clone object copier I found on The Code Project a while ago and incorporated it in our stuff.
正如在其他地方所提到的,它需要你的对象是可序列化。
As mentioned elsewhere, it does require your objects to be serializable.
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
的想法是,将其序列的对象,然后将其反序列化到一个新的对象。这样做的好处是,你不必担心自己有关克隆一切当一个物体变得太复杂了。
The idea is that it serializes your object and then deserializes it into a fresh object. The benefit is that you don't have to concern yourself about cloning everything when an object gets too complex.
和配合使用的扩展方法(也由最初引用来源):
And with the use of extension methods (also from the originally referenced source):
如果你preFER使用的C#3.0新扩展方法,改变方法有以下签名:
In case you prefer to use the new extension methods of C# 3.0, change the method to have the following signature:
public static T Clone<T>(this T source)
{
//...
}
现在的方法调用简直变成 objectBeingCloned.Clone();
Now the method call simply becomes objectBeingCloned.Clone();
.
修改(2015年1月10日),以为我会再次讨论这个,说我最近开始使用(Newtonsoft)JSON来做到这一点,<一个href="http://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/">should被的打火机,并避免了[序列化]标记的开销。 ( NB @atconway指出在私有成员没有使用JSON方法克隆了评论)
EDIT (January 10 2015) Thought I'd revisit this, to mention I recently started using (Newtonsoft) Json to do this, it should be lighter, and avoids the overhead of [Serializable] tags. (NB @atconway has pointed out in the comments that private members are not cloned using the JSON method)
/// <summary>
/// Perform a deep Copy of the object, using Json as a serialisation method.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T CloneJson<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}
这篇关于深克隆对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!