深度克隆对象

我想做一些类似的事情:

MyObject myObj=GetMyObj();//创建并填充新对象
MyObject newObj=myObj.Clone();

然后对原始对象中未反映的新对象进行更改

我并不经常需要这个功能,所以在必要的时候,我会创建一个新的对象,然后分别复制每个属性,但它总是让我觉得有一种更好或更优雅的方式来处理这种情况

如何克隆或深度复制一个对象,以便可以修改克隆的对象,而不会在原始对象中反映任何更改

一种方法是实现ICloneable接口(在这里描述,所以我不会重复),这里有一个很好的深度克隆对象复制器,我不久前在代码项目中找到了它,并将它合并到我们的代码中。
正如其他地方提到的,它要求对象是可序列化的

使用系统;
使用System.IO;
使用System.Runtime.Serialization;
使用System.Runtime.Serialization.Formatters.Binary;
///<总结>
///参考文章http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
///提供用于执行对象的深度复制的方法。
///二进制序列化用于执行复制。
///&lt/总结>
公共静态类对象复制器
{
///<摘要>
///通过序列化执行对象的深度复制。
///</summary>
///“typeparam name=”T“gt;要复制的对象的类型。</typeparam>
///“param name=”源“>要复制的对象实例。</param>
///<返回>对象的深度副本。</returns>
公共静态T克隆<T>(T源)
{
如果(!typeof(T).IsSerializable)
{
抛出新ArgumentException(“类型必须是可序列化的。”,nameof(source));
}
//不要序列化空对象,只需返回该对象的默认值
if(ReferenceEquals(source,null))返回默认值;
使用var Stream=newmemoryStream();
IFormatter formatter=新的BinaryFormatter();
序列化(流、源);
stream.Seek(0,SeekOrigin.Begin);
返回(T)格式化程序。反序列化(流);
}
}

其思想是将对象序列化,然后将其反序列化为新对象。好处是,当对象变得太复杂时,您不必担心克隆所有内容

如果您更喜欢使用C#3.0的新扩展方法,请将该方法更改为具有以下签名:

公共静态T克隆<T>(这是T来源)
{
// ...
}

现在方法调用变成objectbeingclone.Clone()

EDIT(2015年1月10日)我想重新讨论一下,我最近开始使用(Newtonsoft)Json来实现这一点,它应该更轻,并且避免了[Serializable]标记的开销。(NB@atconway在评论中指出,私有成员不是使用JSON方法克隆的)

//<总结>
///使用Json作为序列化方法,执行对象的深度复制。注意:不能使用此方法克隆私有成员。
///&lt/总结>
///<typeparam name=""&燃气轮机;正在复制的对象的类型。&lt/typeparam>
///<参数名称=”引用;资料来源&燃气轮机;要复制的对象实例。&lt/参数>
///<退货>复制的对象。&lt/退货>
公共静态T克隆<T>(这是T来源)
{            
//不要序列化空对象,只需返回该对象的默认值
if(ReferenceEquals(source,null))返回默认值;
//单独初始化内部对象
//例如,在默认构造函数中,某些列表属性使用某些值初始化,
//但在“源”中,这些项目已清理-
//没有ObjectCreationHandling。替换默认构造函数值将添加到结果中
var deserializeSettings=new JsonSerializerSettings{ObjectCreationHandling=ObjectCreationHandling.Replace};
返回JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(源),反序列化设置);
}

发表评论