创建Object的副本

时间:2013-06-12 12:16:16

标签: c# .net-4.5 icloneable

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

  1. 实施ICloneable Interface
  2. 创建自己的克隆机制,如this famous SO answer
  3. 我喜欢拳头方式 - 它更容易,但我也找到Not Implpement ICloneable Interface,但它是非常老的帖子,在MSDN上我找不到这个界面已弃用。

    有人说我,在.net 4.5中使用ICloneable是安全的吗?

2 个答案:

答案 0 :(得分:3)

IClonable只是一个接口,因此在您实现它之前 什么都没有。建议不使用IClonable的帖子提到了原因:不清楚Clone是实现为深层还是浅层副本。

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

引用解释这两个术语:

  

实现ICloneable有两种常规方法,可以是,   或非深副本。深层复制复制克隆的对象和所有对象   由对象引用,递归地直到图中的所有对象   被复制。非深拷贝(如果只是顶部,则称为)   复制级别引用)可以不执行任何操作,也可以是深层复制的一部分。

答案 1 :(得分:1)

您不应使用IClonable接口。

几年前的

Here's a blog from Brad Abrams discussing why not。基本上,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