Top > Programming > CommonTips > ArrayValueIsReferenceType
Last-modified: Mon, 03 Jun 2013 05:55:54 JST
Counter:2055 Today:1 Yesterday:0 Online:2
このエントリーをはてなブックマークに追加

配列は参照型である点に注意する

About

多くのオブジェクト指向プログラミング言語(C#やJava)では参照型と値型という概念があります。値型はint、float、doubleなどで、参照型はクラスのインスタンスや良く利用されるのはstringです。値型と参照型の違いについて、ここでは詳細の説明を割愛するとして、参照型の場合には、値が複製されず、例えばAとBが参照型変数aを持つとき、aの値を変更すると、AのaもBのbの値が変更されます。ところがもし、変数aが値型の場合には、Aのaが変更されてもBのaは変更されません。

ところが値型の場合にも注意する必要があり、例外的に値型の配列は参照型となります。つまり値型の配列X[]のX[0]に代入される値を変更した時、X[]を参照するすべての箇所で値が変更されます。

Sample

C#で適当なシチュエーションを用意しました。配列を値型と思い込むとよくあるミスです。ある値を次のインスタンスに複製しようとする時、配列はそのまま複製すると不具合が起きる、というミスです。

    public class SampleA
    {
        public int data = 0;
        public int[] arrayData = new int[]{ 0, 0, 0 };

        public SampleA()
        {
        }

        public SampleA(SampleA parent)
        {
            this.data = parent.data;
            this.arrayData = parent.arrayData;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            SampleA parent = new SampleA();
            SampleA child = new SampleA(parent);
            Console.WriteLine("Parent - DataArray : " + parent.arrayData[0]);
            Console.WriteLine("Parent - Data : " + parent.data);
            Console.WriteLine("Child - DataArray : " + child.arrayData[0]);
            Console.WriteLine("Child - Data : " + child.data);

            //子供に代入する
            Console.WriteLine("----------------------------------");
            child.arrayData[0] = 1;
            child.data = 1;

            Console.WriteLine("Parent - DataArray : " + parent.arrayData[0]);
            Console.WriteLine("Parent - Data : " + parent.data);
            Console.WriteLine("Child - DataArray : " + child.arrayData[0]);
            Console.WriteLine("Child - Data : " + child.data);

            Console.ReadLine();
        }
    }

出力結果は次の通りです。Parentの配列(DataArray)には値を代入していないのに、Childの配列(DataArray)に値を代入したことで、値が変化していることが確認できます。

Parent - DataArray : 0
Parent - Data : 0
Child - DataArray : 0
Child - Data : 0
----------------------------------
Parent - DataArray : 1
Parent - Data : 0
Child - DataArray : 1
Child - Data : 1

問題の解決は言語や環境によって異なりますが、多くの言語で配列の中身を別の配列へ複製するメソッドや機能などが提供されています。