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