[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
前回の以下の記事は配列の使い方の基本について記しましたが、 今回は配列を使う場合の注意点をまとめてみました。
⇒配列の使い方について(Dim, Redim)
それでは以下の内容で説明したいと思います。
■配列変数のコピー
以下のソースを見て下さい。 最初に配列「arr1」「arr2」を宣言していますが、「arr1」のみ初期化も行っています。
その後、「arr2」に「arr1」を代入しています。 (この代入で「arr2」に「arr1」の内容全てがコピーされた様に思いますが、実際にそうでしょうか。)
「arr1」の2番目の要素クリア後、「arr1」及び「arr2」の内容を全てコンソールに表示させてどうなったかを見てみます。
Private Sub btnArray_Click(sender As Object, e As EventArgs) Handles btnArray.Click '配列宣言 Dim arr1() As Integer = {100, 200, 300} 'こちらは配列初期化有り Dim arr2() As Integer '配列宣言のみ '配列変数のコピー arr2 = arr1 '「arr1」の2番目の要素クリア arr1(1) = 0 '「arr1」の内容表示 For i As Integer = 0 To UBound(arr1) Console.WriteLine("arr1[{0}]:{1}", i, arr1(i)) Next '「arr2」の内容表示 For i As Integer = 0 To UBound(arr2) Console.WriteLine("arr2[{0}]:{1}", i, arr2(i)) Next End Sub
実行結果がコンソールには以下様に表示されます。
arr1[0]:100 arr1[1]:0 arr1[2]:300 arr2[0]:100 arr2[1]:0 arr2[2]:300
予想に反して「arr1」及び「arr2」共に同じ値が表示されました。
どうしてこうなるのかと言いますと、「配列変数のコピー」では配列の中身では無く参照をコピーすることになるからです。 参照とは配列の実体を指し示すポインタと言った方がいいかもしれません。
実は変数「arr1」も配列の実体の参照でしかないということです。 {100, 200, 300} と宣言された配列の実体はどこかにあり、その実体を指し示すポインタを変数「arr1」が保持しています。
実体をコピーしたい場合には配列の Clone メソッドを使います。以下にその様子を示します。
■配列変数の実体コピー(Clone)
上記のソースでは配列変数コピーで単に変数同士のコピーを行いましたが、 以下では配列の Clone メソッドの結果を代入しています。
Private Sub btnArray_Click(sender As Object, e As EventArgs) Handles btnArray.Click '配列宣言 Dim arr1() As Integer = {100, 200, 300} 'こちらは配列初期化有り Dim arr2() As Integer '配列宣言のみ '配列変数の実体コピー arr2 = arr1.Clone '「arr1」の2番目の要素クリア arr1(1) = 0 '「arr1」の内容表示 For i As Integer = 0 To UBound(arr1) Console.WriteLine("arr1[{0}]:{1}", i, arr1(i)) Next '「arr2」の内容表示 For i As Integer = 0 To UBound(arr2) Console.WriteLine("arr2[{0}]:{1}", i, arr2(i)) Next End Sub
実行結果がコンソールには以下様に表示されます。
arr1[0]:100 arr1[1]:0 arr1[2]:300 arr2[0]:100 arr2[1]:200 arr2[2]:300
結果を見れば指標「1」の要素が「arr1」及び「arr2」が異なる値であることが分かります。
Clone メソッドは配列の実体を別に作成し、全ての要素をコピーしその参照を返します。 (Clone 直後は要素の内容は全て同じです。) そのため、「arr1」及び「arr2」は実体が別々の配列となります。
■配列の実体コピー・ディープコピー(Serializable)
以下の記事にもありますが、配列も1個のオブジェクトなので配列の実体をシリアル化して、別の実体にシリアル化を戻せば、 配列のコピーができることになります。
⇒各種オブジェクトのコピーができるディープコピー(BinaryFormatter,MemoryStream,Serialize,Deserialize)
以下のソースに上記の記事内の関数を利用して配列のコピーを行います。
Private Sub btnArray_Click(sender As Object, e As EventArgs) Handles btnArray.Click '配列宣言 Dim arr1() As Integer = {100, 200, 300} 'こちらは配列初期化有り Dim arr2() As Integer '配列宣言のみ '配列の実体コピー・ディープコピー arr2 = DeepCopy(arr1) '「arr1」の2番目の要素クリア arr1(1) = 0 '「arr1」の内容表示 For i As Integer = 0 To UBound(arr1) Console.WriteLine("arr1[{0}]:{1}", i, arr1(i)) Next '「arr2」の内容表示 For i As Integer = 0 To UBound(arr2) Console.WriteLine("arr2[{0}]:{1}", i, arr2(i)) Next End Sub
実行結果がコンソールには以下様に表示されます。
arr1[0]:100 arr1[1]:0 arr1[2]:300 arr2[0]:100 arr2[1]:200 arr2[2]:300
関連する記事
⇒配列の使い方について(Dim, Redim)⇒配列の範囲指定によるコピー(Array.Copy, Skip, Take)
コメント