我想做一些事情,比如:
MyObject myObj = GetMyObj(); // Create and fill a new object
MyObject newObj = myObj.Clone();
然后对未反映在原始对象中的新对象进行更改。
我通常不需要这个功能,所以当有必要时,我会创建一个新对象,然后单独复制每个属性,但这总是让我觉得有更好或更优雅的方法来处理这种情况。
如何克隆或深度复制对象,以便在原始对象中不反映任何更改的情况下修改克隆的对象?
我想做一些事情,比如:
MyObject myObj = GetMyObj(); // Create and fill a new object
MyObject newObj = myObj.Clone();
然后对未反映在原始对象中的新对象进行更改。
我通常不需要这个功能,所以当有必要时,我会创建一个新对象,然后单独复制每个属性,但这总是让我觉得有更好或更优雅的方法来处理这种情况。
如何克隆或深度复制对象,以便在原始对象中不反映任何更改的情况下修改克隆的对象?
当前回答
我更喜欢复制构造函数而不是克隆。意图更加明确。
其他回答
如果使用net.core并且对象是可序列化的,则可以使用
var jsonBin = BinaryData.FromObjectAsJson(yourObject);
then
var yourObjectCloned = jsonBin.ToObjectFromJson<YourType>();
BinaryData在dotnet中,因此您不需要第三方库。它还可以处理类上的属性为Object类型的情况(属性中的实际数据仍然需要可序列化)
我提出这一点是为了克服.NET的一个缺点,即必须手动深度复制List<T>。
我使用这个:
static public IEnumerable<SpotPlacement> CloneList(List<SpotPlacement> spotPlacements)
{
foreach (SpotPlacement sp in spotPlacements)
{
yield return (SpotPlacement)sp.Clone();
}
}
在另一个地方:
public object Clone()
{
OrderItem newOrderItem = new OrderItem();
...
newOrderItem._exactPlacements.AddRange(SpotPlacement.CloneList(_exactPlacements));
...
return newOrderItem;
}
我试图提出一个这样做的oneliner,但这是不可能的,因为yield不能在匿名方法块中工作。
更好的是,使用通用的List<T>克隆器:
class Utility<T> where T : ICloneable
{
static public IEnumerable<T> CloneList(List<T> tl)
{
foreach (T t in tl)
{
yield return (T)t.Clone();
}
}
}
我想要一个克隆器,用于非常简单的对象,主要是基元和列表。如果您的对象是开箱即用的JSON可串行化的,那么这个方法就可以了。这不需要修改或实现克隆类上的接口,只需要一个JSON序列化程序,如JSON.NET。
public static T Clone<T>(T source)
{
var serialized = JsonConvert.SerializeObject(source);
return JsonConvert.DeserializeObject<T>(serialized);
}
此外,您可以使用此扩展方法
public static class SystemExtension
{
public static T Clone<T>(this T source)
{
var serialized = JsonConvert.SerializeObject(source);
return JsonConvert.DeserializeObject<T>(serialized);
}
}
创建扩展:
public static T Clone<T>(this T theObject)
{
string jsonData = JsonConvert.SerializeObject(theObject);
return JsonConvert.DeserializeObject<T>(jsonData);
}
这样称呼:
NewObject = OldObject.Clone();
不使用ICloneable的原因不是因为它没有通用接口。不使用它的原因是因为它很模糊。它不清楚你得到的是浅拷贝还是深拷贝;这取决于实施者。
是的,MemberwiseColone生成一个浅拷贝,但MemberwiseClone的反面不是克隆;可能是DeepClone,但它并不存在。当您通过对象的ICloneable接口使用对象时,您无法知道底层对象执行哪种克隆。(而且XML注释不会很清楚,因为您将得到接口注释,而不是对象的Clone方法上的注释。)
我通常只做一个Copy方法,它完全符合我的要求。