おはよう、昼も夜も、
特定のクラスを不変クラスとして実装し、プライベート/内部フィールドを公開するメソッドやプロパティを持たない場合、浅いコピーは悪い習慣ですか、インスタンス化する必要があるオブジェクトがはるかに少ないため、問題なく実行できますか?
どうもありがとうございました。
おはよう、昼も夜も、
特定のクラスを不変クラスとして実装し、プライベート/内部フィールドを公開するメソッドやプロパティを持たない場合、浅いコピーは悪い習慣ですか、インスタンス化する必要があるオブジェクトがはるかに少ないため、問題なく実行できますか?
どうもありがとうございました。
一般的に言えば (これにはいくつかの例外があるかもしれません)、型が完全に不変である場合は、浅いか深いかを問わず、型をコピーする必要はほとんどありません。元のインスタンスを渡すだけです。
適切に不変な型の大きな利点の 1 つは、同じインスタンスをすべてのコンシューマーに渡すことができることです。他のコンシューマーのためにそれを変更したり破損したりすることはできません。
不変のデータ構造を使用する利点の 1 つは、何かを変更する必要がある場合にのみ浅いコピーを実行することで、はるかに効率的にできることです。明らかに、何も変更しないのであれば、コピーを作成する必要はまったくありません。
たとえば、次のような不変クラスを作成できます。
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;
}
}
サポートする不変性のセマンティクスに依存します。浅いコピーを使用する場合は、共有しているオブジェクトも変更されていないことを保証する必要があります。そうしないと、オブザーバーからの変更として認識されます。これに加えて、オブジェクトを共有することは実際にはパフォーマンスの点で非常に有益です。つまり、これらのオブジェクトは N 回ではなく 1 回だけ必要になります ( Flyweight パターンも参照してください)。
コピーされたオブジェクト (グラフの「第 1 レベル」) が不変であると仮定すると、浅いコピーを行うことをお勧めします。
また、不変オブジェクトは自分自身を返すクローン メソッドを持つことができるため、それらを含むオブジェクトが「ディープ コピー」されると、実際にはそのような浅いコピーになります。たとえば、System.String は次のように ICloneable を実装します。
public object Clone()
{
return this;
}
個人的には、インターフェイスを介して呼び出されない場合にキャストの必要性を減らす次のバリアントをお勧めします。
public class MyImmutableClass : ICloneable
{
public MyImmutableClass Clone()
{
return this;
}
ICloneable.Clone()
{
return this;
}
}