英語で読む

次の方法で共有


Object.MemberwiseClone メソッド

定義

現在の Objectの簡易コピーを作成します。

protected object MemberwiseClone ();

戻り値

現在の Objectの浅いコピー。

次の例は、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)MemberwiseClone();
    }

    public Person DeepCopy()
    {
        Person other = (Person)MemberwiseClone();
        other.IdInfo = new IdInfo(IdInfo.IdNumber);
        return other;
    }
}

public class Example
{
    public static void Main()
    {
        // Create an instance of Person and assign values to its fields.
        Person p1 = new()
        {
            Age = 42,
            Name = "Sam",
            IdInfo = new IdInfo(6565)
        };

        // Perform a shallow copy of p1 and assign it to p2.
        Person p2 = p1.ShallowCopy();

        // Display values of p1, p2
        Console.WriteLine("Original values of p1 and p2:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p2 instance values:");
        DisplayValues(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;
        Console.WriteLine("\nValues of p1 and p2 after changes to p1:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p2 instance values:");
        DisplayValues(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.Age = 39;
        p1.Name = "George";
        p1.IdInfo.IdNumber = 8641;
        Console.WriteLine("\nValues of p1 and p3 after changes to p1:");
        Console.WriteLine("   p1 instance values: ");
        DisplayValues(p1);
        Console.WriteLine("   p3 instance values:");
        DisplayValues(p3);
    }

    public static void DisplayValues(Person p)
    {
        Console.WriteLine($"      Name: {p.Name:s}, Age: {p.Age:d}");
        Console.WriteLine($"      Value: {p.IdInfo.IdNumber:d}");
    }
}

/* 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 プロパティを含む) を元のオブジェクトに影響を与えずに変更できます。

注釈

MemberwiseClone メソッドは、新しいオブジェクトを作成し、現在のオブジェクトの非静的フィールドを新しいオブジェクトにコピーすることで、浅いコピーを作成します。 フィールドが値型の場合、フィールドのビット単位のコピーが実行されます。 フィールドが参照型の場合、参照はコピーされますが、参照されるオブジェクトはコピーされません。したがって、元のオブジェクトとその複製は同じオブジェクトを参照します。

簡易コピー操作とディープ コピー操作の違いを説明するには、オブジェクト A と B を参照する X というオブジェクトを考えます。オブジェクト B は、オブジェクト C を参照します。X の浅いコピーでは、オブジェクト A と B も参照する新しいオブジェクト X2 が作成されます。これに対し、X のディープ コピーでは、新しいオブジェクト A2 と B2 を参照する新しいオブジェクト X2 が作成されます。このオブジェクトは、A と B. B2 のコピーであり、C のコピーである新しいオブジェクト C2 を参照します。

MemberwiseClone メソッドによって実行される簡易コピー操作がニーズを満たしていない場合、ディープ コピー操作を実装する方法は多数あります。 これには、次のものが含まれます。

  • コピーするオブジェクトのクラス コンストラクターを呼び出して、最初のオブジェクトから取得されたプロパティ値を持つ 2 つ目のオブジェクトを作成します。 これは、オブジェクトの値がそのクラス コンストラクターによって完全に定義されていることを前提としています。
  • MemberwiseClone メソッドを呼び出してオブジェクトの浅いコピーを作成し、元のオブジェクトと同じ値を持つ新しいオブジェクトを、値が参照型のプロパティまたはフィールドに割り当てます。 この例の DeepCopy メソッドは、この方法を示しています。
  • 詳細コピーするオブジェクトをシリアル化し、シリアル化されたデータを別のオブジェクト変数に復元します。
  • リフレクションと再帰を使用して、ディープ コピー操作を実行します。

適用対象

製品 バージョン
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 2.0, 2.1
UWP 10.0