ここでは非ジェネリックなコレクション型System.Collections.ArrayListクラスについて解説します。 ArrayListクラスを使用するよりも、ArrayListに相当するジェネリックなコレクション型System.Collections.Generic.List<T>クラスを使用することを強く推奨します。

§1 ArrayList

System.Collections.ArrayListクラスは配列に非常によく似たクラスですが、要素の数が固定である配列とは異なり動的に要素の数を増減できるという特徴を持っています。

§1.1 基本的な操作

早速、ArrayListを使った基本的な操作について見ていきます。 次のコードは、ArrayListクラスを使った例です。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    ArrayList arr = new ArrayList();

    // 要素の追加
    arr.Add(0);
    arr.Add(1);
    arr.Add(2);

    Print(arr);

    // 複数の要素の追加
    arr.AddRange(new int[] {3, 4, 5, 6});

    Print(arr);

    // 要素の削除
    arr.Remove(3);
    arr.Remove(6);

    Print(arr);

    // 特定の位置にある要素を削除
    arr.RemoveAt(0);

    Print(arr);

    // 特定の位置にある要素を変更
    arr[2] = 7;

    Print(arr);

    // 特定の位置に要素を挿入
    arr.Insert(2, 3);

    Print(arr);

    // ArrayListの内容をソート
    arr.Sort();

    Print(arr);

    // ArrayListの内容を反転
    arr.Reverse();

    Print(arr);
  }

  static void Print(ArrayList arr)
  {
    for (int i = 0; i < arr.Count; i++) {
      Console.Write("{0}, ", arr[i]);
    }

    Console.WriteLine();
  }
}
Copyright© 2016 . Released under the WTFPL version 2.
実行結果
0, 1, 2, 
0, 1, 2, 3, 4, 5, 6, 
0, 1, 2, 4, 5, 
1, 2, 4, 5, 
1, 2, 7, 5, 
1, 2, 3, 7, 5, 
1, 2, 3, 5, 7, 
7, 5, 3, 2, 1, 

この例を見てわかるように、ArrayListでは要素の数は可変であるため、任意の数の要素を追加・削除・挿入することが出来ます。 要素の追加・削除・挿入にはAdd, AddRange, Remove, RemoveAt, RemoveRange, Insertなどのメソッドを使います。 Removeメソッドは指定された要素をArrayListから削除するのに対し、RemoveAtメソッドは指定されたインデックスにある要素を削除します。 Clearメソッドによって、コレクション内の全ての要素を削除することも出来ます。 現在の要素の数を取得するには、Lengthプロパティではなく、Countプロパティを参照します。

また、配列と同様に、インデックスを指定して特定の要素を取得・設定することも出来ます。 C#ではインデクサによって、VB.NETでは既定のプロパティItemによって、配列と同様のインデックスによる取得・設定ができるようになっています。

この例ではint型を代入していますが、ArrayListではint型ではなくobject型で要素を格納するので、どのような型でもArrayListに追加することができます。 次の例では、一つのArrayListに様々な型の要素を追加しています。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    ArrayList arr = new ArrayList();

    arr.Add(16);
    arr.Add("foo");
    arr.Add(Math.PI);

    Print(arr);
  }

  static void Print(ArrayList arr)
  {
    for (int i = 0; i < arr.Count; i++) {
      Console.Write("{0}, ", arr[i]);
    }

    Console.WriteLine();
  }
}
Copyright© 2016 . Released under the WTFPL version 2.
実行結果
16, foo, 3.14159265358979,

§1.2 列挙操作

ArrayListでも、配列と同様for文による列挙と、foreach文による列挙ができるようになっています。 次の例では、ArrayListをfor文とforeach文で列挙しています。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    ArrayList arr = new ArrayList();

    arr.Add(16);
    arr.Add("foo");
    arr.Add(Math.PI);

    // for文を使った列挙
    for (int i = 0; i < arr.Count; i++) {
      Console.Write("{0}, ", arr[i]);
    }

    Console.WriteLine();

    // foreach文を使った列挙
    foreach (object e in arr) {
      Console.Write("{0}, ", e);
    }

    Console.WriteLine();
  }
}
Copyright© 2016 . Released under the WTFPL version 2.
実行結果
16, foo, 3.14159265358979, 
16, foo, 3.14159265358979, 

§1.3 配列からの変換

配列からArrayListに変換するには、コンストラクタかAddRangeメソッドが使えます。 既に説明したとおり、配列の型によらずArrayListに変換することができます。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    int[] intArray = new int[] {0, 1, 2};
    string[] stringArray = new string[] {"foo", "bar", "baz"};

    // コンストラクタに配列を指定してArrayListを生成
    ArrayList arr = new ArrayList(stringArray);

    // AddRangeメソッドで配列を追加
    arr.AddRange(intArray);

    Print(arr);
  }

  static void Print(ArrayList arr)
  {
    for (int i = 0; i < arr.Count; i++) {
      Console.Write("{0}, ", arr[i]);
    }

    Console.WriteLine();
  }
}
Copyright© 2016 . Released under the WTFPL version 2.
実行結果
foo, bar, baz, 0, 1, 2, 

§1.4 配列への変換・コピー

ArrayListから配列へ変換する場合にはToArrayメソッドCopyToメソッドが使えます。 ただしArrayListへの変換とは逆に、配列のコピー時にはコピー先となる配列の型に注意する必要があります。 コピーしようとする要素とコピー先の配列の型が異なる(キャスト出来ない)場合はInvalidCastExceptionがスローされます。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    ArrayList arr = new ArrayList();

    arr.Add(1);
    arr.Add(2);
    arr.Add(3);

    arr.Add("foo");
    arr.Add("bar");
    arr.Add("baz");

    // ArrayListの0番目から3要素分をintArrayにコピー
    int[] intArray = new int[3];

    arr.CopyTo(0, intArray, 0, 3);

    foreach (int intVal in intArray) {
      Console.Write("{0}, ", intVal);
    }

    Console.WriteLine();

    // ArrayListの3番目から3要素分をstringArrayにコピー
    string[] stringArray = new string[3];

    arr.CopyTo(3, stringArray, 0, 3);

    foreach (string stringVal in stringArray) {
      Console.Write("{0}, ", stringVal);
    }

    Console.WriteLine();

    // ArrayListの全要素をint型配列に変換
    try {
      intArray = arr.ToArray(typeof(int)) as int[];
    }
    catch (InvalidCastException) {
      Console.WriteLine("InvalidCastException");
    }
  }
}
Copyright© 2016 . Released under the WTFPL version 2.
実行結果
1, 2, 3, 
foo, bar, baz, 
InvalidCastException

ToArrayメソッドで型を指定しなければobjectの配列へ変換することが出来ます。 この場合、InvalidCastExceptionはスローされません。

using System;
using System.Collections;

class Sample {
  static void Main()
  {
    ArrayList arr = new ArrayList();

    arr.Add(1);
    arr.Add(2);
    arr.Add(3);

    arr.Add("foo");
    arr.Add("bar");
    arr.Add("baz");

    object[] objArray = arr.ToArray();

    foreach (object obj in objArray) {
      Console.Write("{0}, ", obj);
    }

    Console.WriteLine();
  }
}
Copyright© 2016 . Released under the WTFPL version 2.
実行結果
1, 2, 3, foo, bar, baz,