28
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【C#】シャローコピーとディープコピー

Last updated at Posted at 2020-12-15

Qiita Advent Calendar 初参加です。よろしくお願いします。
最近学習していて面白いな、と感じたオブジェクトの複製についてまとめました。

オブジェクトの複製パターン

オブジェクトの複製には2つのパターンがあります。

  • シャローコピー:簡易コピー
    参照のみをコピーし、実体を複製しない。
    複製するオブジェクトが値型か参照型かによって、コピー元(先)の変更がコピー先(元)に適用されるかどうかが異なる。
    値型は値がそのまま複製される→ 変更が適用されない
    参照型は参照先のアドレスが複製される→ 変更が適用される
     ※ただし string型 は変更のたびに別のインスタンスが生成されるため、変更が適用されない
     文字列 -C# プログラミング ガイド 文字列の不変性

  • ディープコピー:詳細コピー
    実体を複製する。
    コピー元(元)を変更しても、コピー先(先)に変更が適用されない。

代入・コピーコンストラクタ・MemberwiseCloneメソッド・シリアライズ...etc など様々な方法で上記のコピーを実装することが可能です。今回はシャローコピーを代入・コピーコンストラクタ・MemberwiseCloneメソッド、ディープコピーをMemberwiseCloneメソッドで実装しました。また、コピー後に値を変更し、コピー元(またはコピー先)に影響があるかどうかを検証しました。

※今回の記事では値型と参照型をメソッド内でコピーするコードがありますが、引数を渡していないため「参照渡し」は関係ありません。

image.png

組み込み型メンバを持つ構造体をシャローコピーで複製する

組み込み型をメンバーとして SampleStruct 構造体を作成します。

SampleStruct
    public struct SampleStruct
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public int[] Ids { get; set; }

        public string[] Names { get; set; }

        // 初期化
        public SampleStruct(int id, string name, int[] ids, string[] names)
        {
            Id = id;
            Name = name;
            Ids = ids;
            Names = names;
        }

        // コピーコンストラクタ
        public SampleStruct(SampleStruct sampleStruct)
        {
            Id = sampleStruct.Id;
            Name = sampleStruct.Name;
            Ids = sampleStruct.Ids;
            Names = sampleStruct.Names;
        }

        /// <summary>
        /// シャローコピーを実行します。
        /// </summary>
        /// <returns><see cref="SampleClass2" />が戻ります。</returns>
        public SampleStruct SharrowCopy()
        {
            return (SampleStruct)MemberwiseClone();
        }
    }

1. 代入

上記で作成した SampleStruct を「代入」で複製します。

代入
        public static void ShallowCopy()
        {
            var original = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});

            var copy = original; // 代入

            original.Id = 99;
            original.Name = "Hello, " + "World!";
            original.Ids[0] = 9;
            original.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
Id 99 10 変更が適用されない
Name Hello, World! AAA 変更が適用されない
Ids 9, 2, 3 9, 2, 3 変更が適用された
Names あ, B, C あ, B, C 変更が適用された

2. コピーコンストラクタ

上記で作成した SampleStruct を「コピーコンストラクタ」で複製します。

コピーコンストラクタ
        public static void ShallowCopy2()
        {
            var original = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});

            var copy = new SampleStruct(original); // コピーコンストラクタ

            original.Id = 99;
            original.Name = "Hello, " + "World!";
            original.Ids[0] = 9;
            original.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
Id 99 10 変更が適用されない
Name Hello, World! AAA 変更が適用されない
Ids 9, 2, 3 9, 2, 3 変更が適用された
Names あ, B, C あ, B, C 変更が適用された

3. MemberwiseCloneメソッド

上記で作成した SampleStruct を「MemberwiseCloneメソッド」で複製します。

MemberwiseCloneメソッド
        public static void ShallowCopy3()
        {
            var original = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});

            var copy = original.SharrowCopy(); // MemberwiseCloneメソッドを呼び出す

            original.Id = 99;
            original.Name = "Hello, " + "World!";
            original.Ids[0] = 9;
            original.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
Id 99 10 変更が適用されない
Name Hello, World! AAA 変更が適用されない
Ids 9, 2, 3 9, 2, 3 変更が適用された
Names あ, B, C あ, B, C 変更が適用された

1, 2, 3の実行結果

値型 Id と string型 Name はコピー元のみ変更が適用されますが、参照型 IdsNames は両方に変更が適用されます。

:white_check_mark: 構造体は値型のため、複製すると別のインスタンスが生成されます。
0_result_result.png
1_result_result.png

組み込み型メンバを持つクラスをシャローコピーで複製する

組み込み型をメンバーとして SampleClass クラスを作成します。

SampleClass
    public class SampleClass
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public int[] Ids { get; set; }

        public string[] Names { get; set; }

        // 初期化
        public SampleClass(int id, string name, int[] ids, string[] names)
        {
            Id = id;
            Name = name;
            Ids = ids;
            Names = names;
        }

        // コピーコンストラクタ
        public SampleClass(SampleClass sampleClass)
        {
            Id = sampleClass.Id;
            Name = sampleClass.Name;
            Ids = sampleClass.Ids;
            Names = sampleClass.Names;
        }

        /// <summary>
        /// シャローコピーを実行します。
        /// </summary>
        /// <returns><see cref="SampleClass" />が戻ります。</returns>
        public SampleClass SharrowCopy()
        {
            return (SampleClass)MemberwiseClone();
        }
    }

1. 代入

上記で作成した SampleClass を「代入」で複製します。

代入
        public static void ShallowCopy()
        {
            var original = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var copy = original; // 代入
            
            original.Id = 99;
            original.Name = "Hello, " + "World!";
            original.Ids[0] = 9;
            original.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
Id 99 99 変更が適用された
Name Hello, World! Hello, World! 変更が適用された
Ids 9, 2, 3 9, 2, 3 変更が適用された
Names あ, B, C あ, B, C 変更が適用された

1の実行結果

全ての型に変更が適用されます。

:white_check_mark: クラスは参照型のため、代入すると参照アドレスが渡され同一インスタンスを参照します。
2_result_result.png
3_result_result.png

2. コピーコンストラクタ

上記で作成した SampleClass を「コピーコンストラクタ」で複製します。

コピーコンストラクタ
        public static void ShallowCopy2()
        {
            var original = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var copy = new SampleClass(original); // コピーコンストラクタ

            original.Id = 99;
            original.Name = "Hello, " + "World!";
            original.Ids[0] = 9;
            original.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
Id 99 10 変更が適用されない
Name Hello, World! AAA 変更が適用されない
Ids 9, 2, 3 9, 2, 3 変更が適用された
Names あ, B, C あ, B, C 変更が適用された

3. MemberwiseCloneメソッド

上記で作成した SampleClass を「MemberwiseCloneメソッド」で複製します。

MemberwiseCloneメソッド
        public static void ShallowCopy3()
        {
            var original = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var copy = original.SharrowCopy(); // MemberwiseCloneメソッドを呼び出す 

            original.Id = 99;
            original.Name = "Hello, " + "World!";
            original.Ids[0] = 9;
            original.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
Id 99 10 変更が適用されない
Name Hello, World! AAA 変更が適用されない
Ids 9, 2, 3 9, 2, 3 変更が適用された
Names あ, B, C あ, B, C 変更が適用された

2, 3の実行結果

値型 Id と string型 Name はコピー元のみ変更が適用されますが、参照型 IdsNames は両方に変更が適用されます。

:white_check_mark: コピーコンストラクタ・MemberwiseCloneメソッドで複製すると別のインスタンスが生成されます。
4_result_result.png
5_result_result.png

クラスと構造体をメンバを持つ構造体をシャローコピーで複製する

先程使用した SampleStructSampleClass をメンバーとして SampleStruct2 を作成します。

SampleStruct2
    public struct SampleStruct2
    {
        public SampleStruct SampleStruct;

        public SampleClass SampleClass;

        // 初期化
        public SampleStruct2(SampleStruct sampleStruct, SampleClass sampleClass)
        {
            SampleStruct = sampleStruct;
            SampleClass = sampleClass;           
        }

        // コピーコンストラクタ
        public SampleStruct2(SampleStruct2 sampleStruct2)
        {
            SampleStruct = sampleStruct2.SampleStruct;
            SampleClass = sampleStruct2.SampleClass;
        }

        /// <summary>
        /// シャローコピーを実行します。
        /// </summary>
        /// <returns><see cref="SampleStruct2" />が戻ります。</returns>
        public SampleStruct2 SharrowCopy()
        {
            return (SampleStruct2)MemberwiseClone();
        }
    }

1. 代入

上記で作成した SampleStruct2 を「代入」で複製します。

代入
        public static void ShallowCopy()
        {
            // 構造体
            var sample1 = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});
            // クラス
            var sample2 = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var original = new SampleStruct2(sample1, sample2);
                                   
            var copy = original; // 代入
            
            // 構造体の値を変更     
            original.SampleStruct.Id = 99;
            original.SampleStruct.Name = "Hello, " + "World!";
            original.SampleStruct.Ids[0] = 9;
            original.SampleStruct.Names[0] = "あ";
            
            // クラスの値を変更
            original.SampleClass.Id = 99;
            original.SampleClass.Name = "Hello, " + "World!";
            original.SampleClass.Ids[0] = 9;
            original.SampleClass.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
SampleStruct.Id 99 10 変更が適用されない
SampleStruct.Name Hello, World! AAA 変更が適用されない
SampleStruct.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleStruct.Names あ, B, C あ, B, C 変更が適用された
SampleClass.Id 99 99 変更が適用された
SampleClass.Name Hello, World! Hello, World! 変更が適用された
SampleClass.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleClass.Names あ, B, C あ, B, C 変更が適用された

2. コピーコンストラクタ

上記で作成した SampleStruct2 を「コピーコンストラクタ」で複製します。

コピーコンストラクタ
        public static void ShallowCopy2()
        {
            // 構造体
            var sample1 = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});
            // クラス
            var sample2 = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var original = new SampleStruct2(sample1, sample2);
                                   
            var copy = new SampleStruct2(original); // コピーコンストラクタ
            
            // 構造体の値を変更     
            original.SampleStruct.Id = 99;
            original.SampleStruct.Name = "Hello, " + "World!";
            original.SampleStruct.Ids[0] = 9;
            original.SampleStruct.Names[0] = "あ";
            
            // クラスの値を変更
            original.SampleClass.Id = 99;
            original.SampleClass.Name = "Hello, " + "World!";
            original.SampleClass.Ids[0] = 9;
            original.SampleClass.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
SampleStruct.Id 99 10 変更が適用されない
SampleStruct.Name Hello, World! AAA 変更が適用されない
SampleStruct.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleStruct.Names あ, B, C あ, B, C 変更が適用された
SampleClass.Id 99 99 変更が適用された
SampleClass.Name Hello, World! Hello, World! 変更が適用された
SampleClass.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleClass.Names あ, B, C あ, B, C 変更が適用された

3. MemberwiseCloneメソッド

上記で作成した SampleStruct2 を「MemberwiseCloneメソッド」で複製します。

MemberwiseCloneメソッド
        public static void ShallowCopy3()
        {
            // 構造体
            var sample1 = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});
            // クラス
            var sample2 = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var original = new SampleStruct2(sample1, sample2);
                                   
            var copy = original.SharrowCopy(); // MemberwiseCloneメソッドを呼び出す
            
            // 構造体の値を変更     
            original.SampleStruct.Id = 99;
            original.SampleStruct.Name = "Hello, " + "World!";
            original.SampleStruct.Ids[0] = 9;
            original.SampleStruct.Names[0] = "あ";
            
            // クラスの値を変更
            original.SampleClass.Id = 99;
            original.SampleClass.Name = "Hello, " + "World!";
            original.SampleClass.Ids[0] = 9;
            original.SampleClass.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
SampleStruct.Id 99 10 変更が適用されない
SampleStruct.Name Hello, World! AAA 変更が適用されない
SampleStruct.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleStruct.Names あ, B, C あ, B, C 変更が適用された
SampleClass.Id 99 99 変更が適用された
SampleClass.Name Hello, World! Hello, World! 変更が適用された
SampleClass.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleClass.Names あ, B, C あ, B, C 変更が適用された

1, 2, 3の実行結果

メンバー内の値型である SampleStruct は、値型 Id と string型 Name はコピー元のみ変更が適用されますが、参照型 IdsNames は両方に変更が適用されます。
メンバー内の参照型である SampleClass は、全ての型に変更が適用されます。

:white_check_mark: 構造体は値型のため、複製すると別のインスタンスが生成されます。
6_result_result.png
7_result_result.png

クラスと構造体をメンバを持つクラスをシャローコピーで複製する

先程使用した SampleStructSampleClass をメンバーとして SampleClass2 を作成します。

SampleClass2
    public class SampleClass2
    {
        public SampleStruct SampleStruct;

        public SampleClass SampleClass;

        // 初期化
        public SampleClass2(SampleStruct sampleStruct, SampleClass sampleClass)
        {
            SampleStruct = sampleStruct;
            SampleClass = sampleClass;           
        }

        // コピーコンストラクタ
        public SampleClass2(SampleClass2 sampleClass2)
        {
            SampleStruct = sampleClass2.SampleStruct;
            SampleClass = sampleClass2.SampleClass;
        }

        /// <summary>
        /// シャローコピーを実行します。
        /// </summary>
        /// <returns><see cref="SampleClass2" />が戻ります。</returns>
        public SampleClass2 SharrowCopy()
        {
            return (SampleClass2)MemberwiseClone();
        }
    }

1. 代入

上記で作成した SampleClass2 を「代入」で複製します。

代入
        public static void ShallowCopy1()
        {
            // 構造体
            var sample1 = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});
            // クラス
            var sample2 = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var original = new SampleClass2(sample1, sample2);
                                   
            var copy = original; // 代入
            
            // 構造体の値を変更     
            original.SampleStruct.Id = 99;
            original.SampleStruct.Name = "Hello, " + "World!";
            original.SampleStruct.Ids[0] = 9;
            original.SampleStruct.Names[0] = "あ";
            
            // クラスの値を変更
            original.SampleClass.Id = 99;
            original.SampleClass.Name = "Hello, " + "World!";
            original.SampleClass.Ids[0] = 9;
            original.SampleClass.Names[0] = "あ";
        }                        

<original(コピー元)の値を変更したあとの各変数>

original copy
SampleStruct.Id 99 99 変更が適用された
SampleStruct.Name Hello, World! Hello, World! 変更が適用された
SampleStruct.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleStruct.Names あ, B, C あ, B, C 変更が適用された
SampleClass.Id 99 99 変更が適用された
SampleClass.Name Hello, World! Hello, World! 変更が適用された
SampleClass.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleClass.Names あ, B, C あ, B, C 変更が適用された

1の実行結果

全ての型に変更が適用されます。

:white_check_mark: クラスは参照型のため、代入すると参照アドレスが渡され同一インスタンスを参照します。
8_result_result.png
9_result_result.png

2. コピーコンストラクタ

上記で作成した SampleClass2 を「コピーコンストラクタ」で複製します。

コピーコンストラクタ
        public static void ShallowCopy2()
        {
            // 構造体
            var sample1 = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});
            // クラス
            var sample2 = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var original = new SampleClass2(sample1, sample2);
                                   
            var copy = new SampleClass2(original); // コピーコンストラクタ
            
            // 構造体の値を変更     
            original.SampleStruct.Id = 99;
            original.SampleStruct.Name = "Hello, " + "World!";
            original.SampleStruct.Ids[0] = 9;
            original.SampleStruct.Names[0] = "あ";
            
            // クラスの値を変更
            original.SampleClass.Id = 99;
            original.SampleClass.Name = "Hello, " + "World!";
            original.SampleClass.Ids[0] = 9;
            original.SampleClass.Names[0] = "あ";
        }                        

<original(コピー元)の値を変更したあとの各変数>

original copy
SampleStruct.Id 99 10 変更が適用されない
SampleStruct.Name Hello, World! AAA 変更が適用されない
SampleStruct.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleStruct.Names あ, B, C あ, B, C 変更が適用された
SampleClass.Id 99 99 変更が適用された
SampleClass.Name Hello, World! Hello, World! 変更が適用された
SampleClass.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleClass.Names あ, B, C あ, B, C 変更が適用された

3. MemberwiseCloneメソッド

上記で作成した SampleClass2 を「MemberwiseCloneメソッド」で複製します。

MemberwiseCloneメソッド
        public static void ShallowCopy3()
        {
            // 構造体
            var sample1 = new SampleStruct(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});
            // クラス
            var sample2 = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C" });

            var original = new SampleClass2(sample1, sample2);
                                   
            var copy = original.SharrowCopy(); // MemberwiseCloneメソッドを呼び出す
            
            // 構造体の値を変更     
            original.SampleStruct.Id = 99;
            original.SampleStruct.Name = "Hello, " + "World!";
            original.SampleStruct.Ids[0] = 9;
            original.SampleStruct.Names[0] = "あ";
            
            // クラスの値を変更
            original.SampleClass.Id = 99;
            original.SampleClass.Name = "Hello, " + "World!";
            original.SampleClass.Ids[0] = 9;
            original.SampleClass.Names[0] = "あ";
        }                        

<original(コピー元)の値を変更したあとの各変数>

original copy
SampleStruct.Id 99 10 変更が適用されない
SampleStruct.Name Hello, World! AAA 変更が適用されない
SampleStruct.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleStruct.Names あ, B, C あ, B, C 変更が適用された
SampleClass.Id 99 99 変更が適用された
SampleClass.Name Hello, World! Hello, World! 変更が適用された
SampleClass.Ids 9, 2, 3 9, 2, 3 変更が適用された
SampleClass.Names あ, B, C あ, B, C 変更が適用された

2, 3の実行結果

メンバー内の値型である SampleStruct は、値型 Id と string型 Name はコピー元のみ変更が適用されますが、参照型 IdsNames は両方に変更が適用されます。
メンバー内の参照型である SampleClass は、全ての型に変更が適用されます。

:white_check_mark: コピーコンストラクタ・MemberwiseCloneメソッドで複製すると別のインスタンスが生成されます。
10_result_result.png
11_result_result.png

ディープコピーを実装する

代入・コピーコンストラクタ・MemberwiseCloneメソッドで複製すると、参照型メンバーが必ずシャローコピーになってしまいます。
その為オブジェクトのシャローコピーを作成した後、参照型メンバーをさらに複製する必要があります。

:white_check_mark: メジャーで簡単な方法

  1. MemberwiseCloneメソッドを使用し、別のインスタンスを作成します。
  2. 参照型メンバーがある場合は、そのメンバーを個別に複製します。

1. MemberwiseCloneメソッド

SampleClass というクラスを用意し、MemberwiseCloneメソッド Array.Cloneメソッド を使用して複製します。

SampleClass
    public class SampleClass
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public int[] Ids { get; set; }

        public string[] Names { get; set; }

        // 初期化
        public SampleClass(int id, string name, int[] ids, string[] names)
        {
            Id = id;
            Name = name;
            Ids = ids;
            Names = names;
        }

        /// <summary>
        /// シャローコピーを実行します。
        /// </summary>
        /// <returns><see cref="SampleClass" />が戻ります。</returns>
        public SampleClass SharrowCopy()
        {
            return (SampleClass) MemberwiseClone();
        }

        /// <summary>
        /// ディープコピーを実行します。
        /// </summary>
        /// <returns><see cref="SampleClass" />が戻ります。</returns>
        public SampleClass DeepCopy()
        {
            var clone = SharrowCopy();
            
            // Array.Clone の戻り値は Object のためキャストが必要
            if (clone.Ids != null)
            {
                clone.Ids = (int[]) this.Ids.Clone();
            }

            if (clone.Names != null)
            {
                clone.Names = (string[]) this.Names.Clone();
            }

            return clone;
        }
    }

初期化をし、ディープコピー用のメソッドを呼び出します

ディープコピー
        public static void DeepCopy()
        {
            var original = new SampleClass(10, "AAA", new[] { 1, 2, 3 }, new[] { "A", "B", "C"});
                                   
            var copy = original.DeepCopy();
            
            original.Id = 99;
            original.Name = "Hello, " + "World!";
            original.Ids[0] = 9;
            original.Names[0] = "あ";
        }

<original(コピー元)の値を変更したあとの各変数>

original copy
Id 99 10 変更が適用されない
Name Hello, World! AAA 変更が適用されない
Ids 9, 2, 3 1, 2, 3 変更が適用されない
Names あ, B, C A, B, C 変更が適用されない

コピー元の変更が、コピー先に適用されていないことが分かります。

まとめ

型の種類 シャローコピー ディープコピー
値型 別のインスタンスを参照 別のインスタンスを参照
参照型 同一インスタンスを参照 別のインスタンスを参照
  • 値型 - 構造体:シャローコピー(代入・コピーコンストラクタ・MemberwiseCloneメソッド)
    コピー先がコピー元と別のインスタンスを参照している。
    メンバにstring型以外の参照型が存在する場合、同一インスタンスを参照しているため、変更が適用される。
    7_result_result.png

  • 参照型 - 注意点
    同じ参照型であっても、string型は変更するたびに別のインスタンスが生成される。

  • 参照型 - クラス:シャローコピー(代入)
    コピー先がコピー元のインスタンスを参照している。
    そのため、クラスメンバに値型が存在しても変更が適用される。
    9_result_result.png

  • 参照型 - クラス:シャローコピー(コピーコンストラクタ・MemberwiseCloneメソッド)
    コピー先がコピー元と別のインスタンスを参照している。
    クラスメンバにstring型以外の参照型が存在する場合、同一インスタンスを参照しているため、変更が適用される。
    クラスメンバが値型でも、その種類が構造体の場合、さらにそのメンバが値型か参照型かによって変更が適用されるかどうかが異なる。
    11_result_result.png

記事内で使用したサンプルコードはこちら▶ CSharpDuplicateObjectsSample

参考URL

最後まで見て頂きありがとうございました。

28
35
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?