以前は、オブジェクトのクローンを作成する必要がありましたが、メソッドが実装されていないことがわかり、Clone()
手動で実行する必要がありました(新しいインスタンスを作成し、すべてのプロパティを元のインスタンスから新しいインスタンスにコピーします)
オブジェクトが割り当てられているメモリブロックを複製するのと同じくらい簡単にクローンを作成できないのはなぜですか。したがって、クラスにClone
メソッドがありobject
、.NETのすべてのクラスがそれを継承します。
については他の人がすでに説明していますが、保護されている理由MemberwiseClone
については誰も説明していません。根拠を示してみます。
ここでの問題は、MemberwiseClone
やみくもに状態をコピーすることです。多くの場合、これは望ましくありません。たとえば、オブジェクトには、への参照であるプライベート フィールドがある場合がありますList
。何のように浅いコピーMemberwiseClone
を行うと、同じリストを指す新しいオブジェクトが作成されます。クラスは、リストが他の人と共有されることを期待せずに記述される可能性があります。
または、オブジェクトは、コンストラクターで生成された何らかの ID フィールドを持つことができます。これを複製すると、同じ ID を持つ 2 つのオブジェクトが取得され、ID が一意であると仮定してメソッドであらゆる種類の奇妙なエラーが発生する可能性があります。
または、ソケットまたはファイル ストリームを開き、それへの参照を格納するオブジェクトがあるとします。MemberwiseClone
参照をコピーするだけです。同じストリームへの呼び出しをインターリーブしようとする 2 つのオブジェクトがうまく終了しないことが想像できます。
つまり、「複製」は、任意のオブジェクトに対して明確に定義された操作ではありません。C++ ではデフォルトですべてのクラスに memberwiseoperator=
が提供されているという事実は、それが存在することを人々が忘れてしまい、コピーが意味をなさない、または危険なクラスに対して無効にしないことが非常に多いため、より厄介です (そして、そのようなクラスは驚くほどたくさんあります)。
(少なくとも) 2 種類のクローニングがあります。ほとんどの参考文献は浅いクローン作成と深いクローン作成について述べていますが、実際にはその中間に陰影があります。
重要な問題は、「どれだけコピーするか」と「どれだけ共有するか」の間の緊張です。
、 、および の への参照Order
を含むオブジェクトを考えてみましょう。Customer
Address
List
OrderLines
したい場合Clone()
はOrder
、何が関係していますか?
「メモリブロックをコピーするだけ」で、新しいが、Order
共有されたものと同じものが得られます。(オブジェクト メンバーは参照によって格納されることに注意してください。そのため、メモリ ブロックを複製すると、同じオブジェクトへの 2 つの参照が作成されます)。Customer
Address
List
OrderLines
明らかに、2 つの 間List
で ofを共有したくありません。実際、それぞれのクローンも作成したいと思うでしょう。OrderLines
Order
OrderLine
汎用Clone()
メソッドを使用している場合、そのメソッドはどのメンバーを再帰的に複製する必要があり、どのメンバーを複製すべきでないかをどのように判断しますか?
一般的に言えば、これは扱いにくい問題です。そのため、状況に応じて適切なセマンティクスを実装するのは個々のオブジェクト次第です。
最後に 1 つ:Clone()
オブジェクトに対する機能を作成する場合でも、メソッドを作成する傾向はClone()
なく、代わりにコピー コンストラクター(別のオブジェクトをベースとして受け入れるコンストラクター) を好みます。見つからない場合はClone()
、それを探してください。