MemberwiseCloneメソッドは浅いコピーを作成し、具体的には、新しいオブジェクトを作成し、新しいオブジェクトに現在のオブジェクトの非静的フィールドをコピーすることです。
フィールドが値型の場合、フィールドは、ビットコピーによってビットを行います。フィールドが参照型である場合、参照をコピーするが、参照されるオブジェクトをコピーしない。したがって、元のオブジェクトのコピーを、同じオブジェクトを参照。
ディープコピーを達成するために、我々は、各構成を参照トラバース図オブジェクト、および基準構造を必要とする処理サイクルを有していなければなりません。これは間違いなく非常に複雑です。幸いなことに、シリアル化の手段とデシリアライズ機構によって.NETは非常に単純な深クローンオブジェクトとすることができます。原理は、状態がメモリーに保存されたオブジェクトとオブジェクトのオブジェクト参照でメモリに最初のオブジェクトのシリアル化ストリーム、簡単です。純直列化機構は、自動的に循環参照の取り扱い。メモリのステータス情報は、新しいオブジェクトにストリームをデシリアライズされます。オブジェクトのような深いコピーが完了しています。プロトタイプのデザインモードクローン技術では非常に重要です。
次のコードは、問題を示しています。
システムを使用しました。 System.IOを使用しました。 System.Runtime.Serialization.Formatters.Binaryを使用しました。 名前空間CloneDemo { [直列化] クラスDemoClass { 公共のint i = 0; 公共のint [] iArr = {1、2、3}。 公共DemoClass Clone1()//浅CLONE { DemoClassとしてthis.MemberwiseClone()を返します。 } 公共DemoClass Clone2()//深クローン { MemoryStreamをストリーム=新しいのMemoryStream()。 BinaryFormatterフォーマッタ=新にBinaryFormatter(); formatter.Serialize(流れ、この)。 stream.Position = 0; DemoClassとしてformatter.Deserialize(ストリーム)を返します。 } } クラスプログラム { 静的メイン(文字列[]引数)無効 { DemoClass新しい新しいDemoClass A =を(); AI = 10; a.iArr =新しい新しいINT [] {8 ,. 9、10}; DemoClass a.Clone1 B =(); DemoClass C a.Clone2 =(); //オブジェクトiArr bで得られた、[0]ターゲットiArrを変更する[0]、Cは変更せずに変更された a.iArr [0] = 88; Console.WriteLineを(「MemberwiseClone "); Console.WriteLineを(BI); foreachのb.iArr varに(アイテム) { Console.WriteLineを(項目); } Console.WriteLineを(" clone2「); Console.WriteLineを(CI); foreachの(VARアイテム)c.iArr中 { Console.WriteLineを(項目); } Console.ReadLine(); } } }
別の例は、配列のためである、配列のC#が、私たちは、配列を実証し、参照型の変数です:
浅いコピー
システムを使用しました。 クラスShallowCopy:ICloneable { 公共のint [] V = {1,2,3}。 パブリックオブジェクトのクローン() { (this.MemberwiseCloneを返します)。 } 公共ボイドディスプレイ() { foreachの(V IにINT) Console.Write(I + ""); Console.WriteLineを(); } } クラスクライアント { 公共の静的な無効メイン() { ShallowCopy SC1 =新しいShallowCopy()。 ShallowCopy SC2 =(ShallowCopy)sc1.Clone(); sc1.v [0] = 9。 sc1.Display(); sc2.Display(); } }
ShallowCopyオブジェクトは浅いコピーを実装し、したがって場合SC1クローニング、そのフィールドVとフィールドのV SC1及びSC2をもたらすないクローンは、同じVを指していない、したがって、ときに変更のV SC1 [0] 、V [0]にSC2が変更されました。
ディープコピー:
システム使用; クラスDeepCopy:ICloneable { 公共のint []はV = {1,2,3}; //デフォルトコンストラクタの パブリックDeepCopy() { } のプライベートコンストラクタメソッド呼び出し//クローン プライベートDeepCopyは([] V int型) { this.v =(INT [])v.Clone(); } パブリックオブジェクトクローン() { // DeepCopyコンストラクト新しいオブジェクトパラメータが設定されている 元のオブジェクトで使用されるV // 新しいDeepCopyを返す(この.V); } 公共ボイドディスプレイ() { foreachの(V IにINT) Console.Write(I + ""); Console.WriteLineを(); } } クラスクライアント { 公共の静的な無効メイン() { DeepCopy DC1 =新しいDeepCopy(); DeepCopy DC2 =(DeepCopy)dc1.Clone(); dc1.v [0] = 9。 dc1.Display(); dc2.Display(); } }
時間のクローニングは、だけでなく、クローニング一緒に偶数フィールドの配列内で、自分自身のクローンを作成します。したがって、最終的なプリントアウトDC1とDC2異なります。
もちろん、我々はまた、クラスのディープコピーの構築を支援することができます:
パブリック静的クラスObjectCopier { /// <要約> ///オブジェクトのディープコピーを実行します。 /// </要約> /// <typeparam名= "T">オブジェクトの種類がコピーされている。</ typeparam> /// <PARAM NAME = "ソース"> </ PARAM>コピーするオブジェクトインスタンス /// <リターン>コピーしたオブジェクト。</リターン> のpublic static Tクローン<T>(Tソース) { 場合(!typeof演算(T).IsSerializable) { 新しいArgumentExceptionがスローを( "タイプは、シリアライズ可能でなければなりません。"、 "ソース"); } //単にそのオブジェクトの既定値を返し、nullオブジェクトをシリアライズしないでください 、もし(Object.ReferenceEquals(ソース NULL)) { 戻りデフォルト(T)。 } IFormatterフォーマッタ=新にBinaryFormatter(); ストリームstream =新しいのMemoryStream(); (ストリーム)を使用して { formatter.Serialize(ストリームソース)。 stream.Seek(0、SeekOrigin.Begin)。 リターン(T)formatter.Deserialize(ストリーム)。 } } }