配列の長さを初期化後に変更する

C#で配列の長さを初期化後に変更するコードを紹介します。

概要

初期のC#では配列は固定配列となるため、配列の長さを後から変更することや、配列に要素を追加することはできませんでしたが、 ジェネリクスが導入された版から、配列の長さを変更する Array.Resize メソッドが利用できるようになりました。
この記事では、Array.Resize メソッドを利用して配列のサイズを動的に変更するコードと、Array・Resize が利用できない場合の 対処方法のコードについて紹介します。

配列の長さを初期化後に変更する : Array.Resize を利用する

Array.Resizxeを利用すると配列初期化後に配列の長さを変更できます。

書式

Array.Resize<配列の要素の型>(長さを変更する配列, 新しい配列の長さ);
配列の長さを変更した場合でも、配列の要素に代入されている値は保持されます。

記述例

次のコードは、int myarray[] 配列の長さを 18 に変更します。
Array.Resize<int>(myarray, 18);
次のコードは、string data[] 配列の長さを 6 に変更します。
Array.Resize<string>(data, 6);

プログラム例

Windows Formアプリケーションを作成します。

UI

下図のフォームを作成します。複数行のテキストボックスとボタンを配置します。

コード

下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ArrayDemo
{
  public partial class FormArrayResize : Form
  {
    public FormArrayResize()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      string[] strArray = new string[3];
      strArray[0] = "ペンギン";
      strArray[1] = "くじら";
      strArray[2] = "しろくま";

      Array.Resize<string>(ref strArray, 4);

      strArray[3] = "あひる";

      foreach (string item in strArray) {
        textBox1.Text += item + "\r\n";
      }
    }
  }
}

解説

string型の長さ3の配列を宣言と作成をし各要素に文字列の値を代入しています。
  string[] strArray = new string[3];
  strArray[0] = "ペンギン";
  strArray[1] = "くじら";
  strArray[2] = "しろくま";

Array.Resize メソッドを呼び出し、先ほど作成した配列の長さを4に増やします。
  Array.Resize<string>(ref strArray, 4);

増えた4番目の要素に文字列の値を代入します。
      strArray[3] = "あひる";

配列の要素の値をテキストボックスに表示します。
  foreach (string item in strArray) {
    textBox1.Text += item + "\r\n";
  }

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。


[button1]をクリックします。配列に格納されている値がテキストボックスに表示されます。 Array.Resizeで配列の長さが4になっていること、 Array.Resizeで配列の長さを変更した場合でも元の値は配列に保持されていることが確認できます。

配列の長さを短くした場合の動作

Array.Resizeを利用して配列の長さを元の長さよりも短くした場合の動作も確認します。

UI

下図のフォームを作成します。([button1]は利用しません。)

コード

以下のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ArrayDemo
{
  public partial class FormArrayResize : Form
  {
    public FormArrayResize()
    {
      InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {
      string[] strArray = new string[6];
      strArray[0] = "ペンギン";
      strArray[1] = "くじら";
      strArray[2] = "しろくま";
      strArray[3] = "かるがも";
      strArray[4] = "あひる";
      strArray[5] = "らくだ";

      Array.Resize<string>(ref strArray, 4);

      foreach (string item in strArray) {
        textBox1.Text += item + "\r\n";
      }
    }

  }
}

解説

以下のコードで配列長6の配列を宣言、作成し要素に値を代入しています。
  string[] strArray = new string[6];
  strArray[0] = "ペンギン";
  strArray[1] = "くじら";
  strArray[2] = "しろくま";
  strArray[3] = "かるがも";
  strArray[4] = "あひる";
  strArray[5] = "らくだ";

配列の長さを4に縮めます。
  Array.Resize<string>(ref strArray, 4);

配列の内容をテキストボックスに表示します。
  foreach (string item in strArray) {
    textBox1.Text += item + "\r\n";
  }

実行結果

プロジェクトを実行します。下図のフォームが表示されます。[button2]をクリックします。


テキストボックスに結果が表示されます。配列を短くした場合、後ろの要素がカットされることが確認できます。

配列の長さを初期化後に変更する : Array.Resize を利用しない場合

Array.Resize が利用できない場合、C#では配列は固定配列となるため、配列の長さを後から変更することや、配列に要素を追加することはできません。

下記のコードでは同名の変数に再度配列を初期化することで配列の長さを変更できますが、格納されていた値はすべてクリアされてしまいます。

同名の変数で初期化しなおす例

コード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ArrayDemo
{
  public partial class FormReArrayDemo : Form
  {
    public FormReArrayDemo()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      string[] strArray = new string[3];

      strArray[0] = "ペンギン";
      strArray[1] = "くじら";
      strArray[2] = "しろくま";

      strArray = new string[4];
      strArray[3] = "あひる";

      foreach (string item in strArray) {
        textBox1.Text += item + "\r\n";
      }
    }
  }
}

解説

同名の配列で初期化しなおした場合、元の配列に格納されていた値は初期化されてしまいます。配列の初期化後に代入した値のみがテキストボックスに表示されます。

実行結果

配列の初期化後に代入された値「あひる」のみがテキストボックスに表示されます。

同名の変数で初期化しなおし、元の配列のコピーから書き戻す例

コード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ArrayDemo
{
  public partial class FormReArrayDemo : Form
  {
    public FormReArrayDemo()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      /* 省略 */
    }

    private void button2_Click(object sender, EventArgs e)
    {
      string[] strArray = new string[3];

      strArray[0] = "ペンギン";
      strArray[1] = "くじら";
      strArray[2] = "しろくま";

      string[] tempArray = new string[3];
      strArray.CopyTo(tempArray,0);

      strArray = new string[tempArray.Length+1];
      tempArray.CopyTo(strArray, 0);
      
      /*
      //オーソドックスな方法
      for (int i = 0; i < tempArray.Length; i++) {
        strArray[i] = tempArray[i];
      }
      */

      strArray[tempArray.Length] = "あひる";

      foreach (string item in strArray) {
        textBox1.Text += item + "\r\n";
      }
    }
  }
}

解説

先の例では配列の初期化により値が初期化されてしまうことが確認できました。これを防ぐため、一度テンポラリの配列に値を格納し、再度配列を初期化した後にテンポラリの配列から元の配列に値を代入しなおします。代入しなおした後追加の配列の要素の値を代入しています。

実行結果

元の配列の値に、新しく追加した「あひる」の値もテキストボックスに表示されます。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2016-07-22
iPentec all rights reserverd.