开发者

Shallow vs. Deep Copies in Immutable Objects

Good morning, afternoon or night,

When implementing a given class as an immutable one, with no methods or properti开发者_运维百科es exposing private/internal fields in any way, is shallow copying a bad practice or can it be done with no problems since it may require a lot less objects to be instantiated?

Thank you very much.


Generally speaking (and there may be some exceptions to this), if your type is completely immutable it is rarely necessary to copy it at all, shallow or deep. You can just pass around the original instance.

One of the great advantages of properly immutable types is that I can pass around the same instance to all consumers, safe in the knowledge that none of them can alter it and corrupt it for another consumer.


One of the advantages of using immutable data structures is that you can be much more efficient by only doing shallow copies when you need to change something. Obviously, you don't need to make any copy at all if you're not changing anything.

For example, you could have an immutable class like this:

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;
    }
}


It depends on the semantics of immutability you want to support - if you use a shallow copy you have to be guaranteed that the objects that you are sharing are not changing either, otherwise this would be perceived as a change from an observer. Besides this, sharing objects can actually be very beneficial in terms of performance, i.e. you need those objects only once as opposed to N times (also see Flyweight pattern).


Assuming you mean that the objects copied (the "first level" in the graph) are immutable, then doing a shallow copy is good practice.

Also, immutable objects can have clone methods returning themselves, so if an object containing them is "deep copied" it will really be such a shallow copy. System.String for example, implements ICloneable with:

public object Clone()
{
  return this;
}

Personally, I'd recommend the following variant that reduces the need for casting when not called through the interface:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜