転職を繰り返したサラリーマンの多趣味ブログ

30才未経験でSEに転職した人の多趣味ブログ

C#を勉強する②_値型と参照型を理解する。

分かったつもりになっても、ちょっと時間がたてば混乱するのが値型と参照型の違い。
まず、例となるソースコードを書いてみた。ちなみに、構造体は値型。

public class Program {

        public static void Main(string[] args) {

            MyClass myClass = new MyClass();
            MyStruct myStruct = new MyStruct();

            // それぞれに値を代入
            myClass.X = 80;
            myStruct.X = 40;

            // メソッドでそれぞれの値を出力(結果:MyClassX = 160, MyStructX = 80)
            PrintObjects(myClass, myStruct);

            // 再度、それぞれの値を出力(結果:MyClassX = 160, MyStructX = 40)
            Console.WriteLine("MyClassX:{0}, MyStructX:{1}", myClass.X, myStruct.X);
        }

        static void PrintObjects(MyClass myclass, MyStruct myStruct) {

            // プロパティの値を2倍
            myclass.X *= 2;
            myStruct.X *= 2;

            Console.WriteLine("MyClassX:{0},MyStructX:{1}", myclass.X, myStruct.X);

        }

        
        
    }

    class MyClass {
        public int X { get; set; }
        public int Y { get; set; }
    }

    struct MyStruct {
        public int X { get; set; }
        public int Y { get; set; }
    }

ここで2回目のConsoleへの出力結果を見てみると、MyStruct(値型)の値は2倍されていないのに、MyClass(参照型)の値は2倍されている。
PrintObjectsメソッド内でMyClass.Xの値を更新しているが、参照型の場合、文字通り参照先の値を更新するため、2回目にMyClass.Xの値を参照した場合、2倍に更新された値を参照しているからである。
では、値型はなぜ2倍になっていないかというと、PrintObjectsメソッドにMyStructを渡しているが、これはオブジェクトそのものをコピーして、メソッドに渡しているからだ。
よって、メソッド内で2倍しても、2回目の出力時にMyStruct.Xの値は2倍になっていない。PrintObjectsメソッドに渡したMyStructと、Mainクラス内で宣言したMyStructは別物である。

参照型はわかるが、値型をメソッドに渡すとき、オブジェクトをコピーして渡しているという概念を自分は忘れがちなので、ここで復習しておく。