我需要在。net 4.5 (c#)中克隆对象(类,而不是结构)。
我找到了两种方法:
- 实现iclonable Interface
- 创建自己的克隆机制,就像这个著名的SO答案
我喜欢第一种方式-它更容易,但我也发现了不实现iclonable接口,但它是非常旧的帖子,在MSDN上我找不到这个接口弃用。
有人能告诉我,在。net 4.5中使用iclonable是安全的吗?IClonable
只是一个接口,所以在您实现它之前,它不做任何事情。建议不使用IClonable
的帖子提到了原因:不清楚Clone
是作为深拷贝还是浅拷贝实现的。
所以只要提供一个Copy
或DeepClone
方法,每个人都知道会发生什么。
引用来解释这两个术语:
有两种实现iclonable的一般方法,要么作为深度,或者非深度拷贝。深拷贝对克隆对象和所有对象进行拷贝由对象引用,递归地直到图中的所有对象被复制。如果只是顶部,则非深拷贝(称为浅拷贝级别引用被复制)可以不做任何操作,或者是深度复制的一部分。
你不应该使用IClonable接口。
这是Brad Abrams几年前写的一篇关于为什么不写的博客。基本上,蒂姆·施梅尔特的回答概述了原因,但这篇博客是来自马的嘴。
关于通过序列化实现克隆,现在有一个稍微好一点的方法可用,因为我们可以指定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
。