0

我需要在 .net 4.5 (c#) 中克隆对象(类,而不是结构)。
我找到了两种方法:

  1. 实现ICloneable 接口
  2. 像这个著名的 SO 答案一样创建自己的克隆机制

我喜欢拳头方式 - 它更容易,但我也发现Not Implpement ICloneable Interface,但这是非常旧的帖子,在 MSDN 上我找不到这个接口已弃用。

有人可以说,在.net 4.5 中使用 ICloneable 是否安全?

4

2 回答 2

3

IClonable只是一个接口,所以在你实现它之前它什么都不做建议不要使用的帖子IClonable提到了原因:不清楚Clone是作为深拷贝还是浅拷贝实现。

所以只需提供一个CopyorDeepClone方法,每个人都知道会发生什么。

引用来解释这两个术语:

实现 ICloneable 的一般方法有两种,一种是深度拷贝,一种是非深度拷贝。深拷贝复制克隆的对象和该对象引用的所有对象,递归地复制,直到图中的所有对象都被复制。非深拷贝(如果只拷贝顶层引用,则称为浅拷贝)可能什么都不做,或者是深拷贝的一部分。

于 2013-06-12T12:21:57.843 回答
1

您不应该使用 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.

于 2013-06-12T12:36:17.383 回答