Object.MemberwiseClone メソッド
2013/03/11
現在の Object の簡易コピーを作成します。
アセンブリ: mscorlib (mscorlib.dll 内)
MemberwiseClone メソッドは、新しいオブジェクトを作成し、現在のオブジェクトの非静的フィールドをその新しいオブジェクトにコピーすることによって、簡易コピーを作成します。フィールドが値型の場合、そのフィールドはビット単位でコピーされます。フィールドが参照型の場合、参照はコピーされますが、参照先オブジェクトはコピーされないため、元のオブジェクトとその複製は同じオブジェクトを参照します。
たとえば、オブジェクト A と B を参照する X というオブジェクトを考えてみます。オブジェクト B はオブジェクト C を参照しています。X の簡易コピーでは、オブジェクト A と B を参照する新しいオブジェクト X2 が作成されます。これに対して、X の詳細コピーでは、A と B のコピーである新しいオブジェクト A2 と B2 を参照する新しいオブジェクト X2 が作成されます。B2 は、C のコピーである新しいオブジェクト C2 を参照します。この例は、簡易コピー操作と詳細コピー操作の違いを示しています。
MemberwiseClone メソッドによって実行される簡易コピー操作がニーズを満たさない場合、詳細コピー操作を実装する方法は多数あります。次に例を示します。
コピーするオブジェクトのクラス コンストラクターを呼び出して、最初のオブジェクトから取得したプロパティ値で 2 番目のオブジェクトを作成します。これは、オブジェクトの値が、クラス コンストラクターによって完全に定義されていることを前提としています。
MemberwiseClone メソッドを呼び出して、オブジェクトの簡易コピーを作成し、値が元のオブジェクトと同じ新しいオブジェクトを値が参照型のプロパティまたはフィールドに割り当てます。例の中の DeepCopy メソッドは、このアプローチを示しています。
詳細コピーされるオブジェクトをシリアル化した後、シリアル化されたデータを別のオブジェクト変数に復元します。
再帰でリフレクションを使用して、詳細コピー操作を実行します。
MemberwiseClone メソッドの例を次に示します。この例では、MemberwiseClone メソッドを呼び出して Person オブジェクトのシャロー コピー操作を実行する ShallowCopy メソッドを定義します。また、Person オブジェクトの詳細コピー操作を実行する DeepCopy メソッドを定義します。
using System; public class IdInfo { public int IdNumber; public IdInfo(int IdNumber) { this.IdNumber = IdNumber; } } public class Person { public int Age; public string Name; public IdInfo IdInfo; public Person ShallowCopy() { return (Person)this.MemberwiseClone(); } public Person DeepCopy() { Person other = (Person)this.MemberwiseClone(); other.IdInfo = new IdInfo(this.IdInfo.IdNumber); return other; } } public class Example { public static void Demo(System.Windows.Controls.TextBlock outputBlock) { // Create an instance of Person and assign values to its fields. Person p1 = new Person(); p1.Age = 42; p1.Name = "Sam"; p1.IdInfo = new IdInfo(6565); // Perform a shallow copy of p1 and assign it to p2. Person p2 = (Person)p1.ShallowCopy(); // Display values of p1, p2 outputBlock.Text += "Original values of p1 and p2:" + "\n"; outputBlock.Text += " p1 instance values: " + "\n"; DisplayValues(outputBlock, p1); outputBlock.Text += " p2 instance values:" + "\n"; DisplayValues(outputBlock, p2); // Change the value of p1 properties and display the values of p1 and p2. p1.Age = 32; p1.Name = "Frank"; p1.IdInfo.IdNumber = 7878; outputBlock.Text += "\nValues of p1 and p2 after changes to p1:" + "\n"; outputBlock.Text += " p1 instance values: " + "\n"; DisplayValues(outputBlock, p1); outputBlock.Text += " p2 instance values:" + "\n"; DisplayValues(outputBlock, p2); // Make a deep copy of p1 and assign it to p3. Person p3 = p1.DeepCopy(); // Change the members of the p1 class to new values to show the deep copy. p1.Name = "George"; p1.Age = 39; p1.IdInfo.IdNumber = 8641; outputBlock.Text += "\nValues of p1 and p3 after changes to p1:" + "\n"; outputBlock.Text += " p1 instance values: " + "\n"; DisplayValues(outputBlock, p1); outputBlock.Text += " p3 instance values:" + "\n"; DisplayValues(outputBlock, p3); } public static void DisplayValues(System.Windows.Controls.TextBlock outputBlock, Person p) { outputBlock.Text += String.Format(" Name: {0:s}, Age: {1:d}", p.Name, p.Age) + "\n"; outputBlock.Text += String.Format(" Value: {0:d}", p.IdInfo.IdNumber) + "\n"; } } // The example displays the following output: // Original values of p1 and p2: // p1 instance values: // Name: Sam, Age: 42 // Value: 6565 // p2 instance values: // Name: Sam, Age: 42 // Value: 6565 // // Values of p1 and p2 after changes to p1: // p1 instance values: // Name: Frank, Age: 32 // Value: 7878 // p2 instance values: // Name: Sam, Age: 42 // Value: 7878 // // Values of p1 and p3 after changes to p1: // p1 instance values: // Name: George, Age: 39 // Value: 8641 // p3 instance values: // Name: Frank, Age: 32 // Value: 7878
この例では、Person.IdInfo プロパティは、IdInfo オブジェクトを返します。出力を見るとわかるように、MemberwiseClone メソッドを呼び出すことによって Person オブジェクトが複製された場合、複製された Person オブジェクトは、同じ Person.IdInfo オブジェクト参照を共有している点を除けば、元のオブジェクトの独立したコピーです。その結果、複製の Person.IdInfo プロパティを変更すると、元のオブジェクトの Person.IdInfo プロパティが変更されます。一方、詳細コピー操作が実行された場合、クローンされた Person オブジェクト (Person.IdInfo プロパティを含む) は元のオブジェクトに影響を与えることなく変更されます。