我需要在 .net 4.5 (c#) 中克隆对象(类,而不是结构)。
我找到了两种方法:
- 实现ICloneable 接口
- 像这个著名的 SO 答案一样创建自己的克隆机制
我喜欢拳头方式 - 它更容易,但我也发现Not Implpement ICloneable Interface,但这是非常旧的帖子,在 MSDN 上我找不到这个接口已弃用。
有人可以说,在.net 4.5 中使用 ICloneable 是否安全?
我需要在 .net 4.5 (c#) 中克隆对象(类,而不是结构)。
我找到了两种方法:
我喜欢拳头方式 - 它更容易,但我也发现Not Implpement ICloneable Interface,但这是非常旧的帖子,在 MSDN 上我找不到这个接口已弃用。
有人可以说,在.net 4.5 中使用 ICloneable 是否安全?
IClonable
只是一个接口,所以在你实现它之前它什么都不做。建议不要使用的帖子IClonable
提到了原因:不清楚Clone
是作为深拷贝还是浅拷贝实现。
所以只需提供一个Copy
orDeepClone
方法,每个人都知道会发生什么。
引用来解释这两个术语:
实现 ICloneable 的一般方法有两种,一种是深度拷贝,一种是非深度拷贝。深拷贝复制克隆的对象和该对象引用的所有对象,递归地复制,直到图中的所有对象都被复制。非深拷贝(如果只拷贝顶层引用,则称为浅拷贝)可能什么都不做,或者是深拷贝的一部分。
您不应该使用 IClonable 接口。
这是 Brad Abrams 的博客,讨论了几年前的原因。基本上,Tim Schmelter 的回答都概括了原因,但这篇博文却是马马虎虎。
关于通过序列化实现克隆,现在有一种更好的方法,因为我们可以指定StreamingContextStates.Clone
允许克隆更好地处理非托管句柄之类的东西。
Jeffrey Richter 在“CLR via C# 4th Edition”中有一个规范的实现,如下所示:
public static object DeepClone(object original)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter
{
Context = new StreamingContext(StreamingContextStates.Clone)
};
formatter.Serialize(stream, original);
stream.Position = 0;
return formatter.Deserialize(stream);
}
}
或强类型变体:
public static T DeepClone<T>(T original)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "original");
}
if (ReferenceEquals(original, null))
{
return default(T);
}
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter
{
Context = new StreamingContext(StreamingContextStates.Clone)
};
formatter.Serialize(stream, original);
stream.Position = 0;
return (T) formatter.Deserialize(stream);
}
}
我认为您应该(在可能的情况下)使用它而不是实现IClonable
.