不可变对象中的浅与深拷贝

时间:2011-03-22 17:37:43

标签: c# immutability deep-copy shallow-copy

早上好,下午或晚上,

当将一个给定的类实现为一个不可变的类时,没有任何方法或属性以任何方式暴露私有/内部字段,是浅层复制一个不好的做法,或者它可以毫无问题地完成,因为它可能需要更少的对象实例化?

非常感谢。

4 个答案:

答案 0 :(得分:7)

一般来说(并且可能存在一些例外),如果您的类型完全不可变,则很少需要复制它,浅或深。你可以传递原始实例。

正确不可变类型的一大优势是我可以将相同的实例传递给所有消费者,安全地知道他们都不能改变它并为另一个消费者破坏它。

答案 1 :(得分:4)

使用不可变数据结构的一个优点是,只需在需要更改内容时执行浅拷贝,就可以提高效率。显然,如果你没有改变任何东西,你根本不需要复制任何副本。

例如,您可以拥有这样的不可变类:

class Data
{
    ...

    Datum x;
    public Datum X { get { return x; } }
    public Data WithX(Datum x)
    {
        var newData = (Data)this.MemberwiseClone(); // <-- Shallow copy!
        newData.x = x;
        return newData;
    }
}

答案 2 :(得分:2)

这取决于你想要支持的不变性的语义 - 如果你使用浅拷贝,你必须保证你正在共享的对象也不会改变,否则这将被视为观察者的变化。除此之外,共享对象实际上在性能方面实际上是非常有益的,即您只需要这些对象一次而不是N次(另请参阅Flyweight pattern)。

答案 3 :(得分:0)

假设你的意思是复制的对象(图中的“第一级”)是不可变的,那么做一个浅拷贝是很好的做法。

此外,不可变对象可以让克隆方法自行返回,因此如果包含它们的对象被“深度复制”,那么它实际上就是这么浅的副本。例如,System.String通过以下方式实现ICloneable:

public object Clone()
{
  return this;
}

就个人而言,我建议使用以下变体,以便在未通过界面调用时减少投射需求:

public class MyImmutableClass : ICloneable
{
  public MyImmutableClass Clone()
  {
    return this;
  }
  ICloneable.Clone()
  {
    return this;
  }
}