C#で、動的配列を扱う

実際には動的に拡張する配列は存在しないと思うが、Listクラスを使うと似たようなことができる。
System.Collections.GenericにListクラスの他にもいくつか種類があるので列挙。

自分的によく使いそうなもの。
・Listクラス
・Dictionaryクラス

下記は説明。

Listクラス

要素を順序づけて格納するクラスで、番号を使って要素にアクセスできる。
動的配列のように使うことができる。
本エントリーの主役。

※かつてListに似たクラスとしてArrayListといったクラスがあったが、
これは危険なので使わないようにする。Listはこれの代替として作られた。

ソース例

// 初期宣言
var list = new List<string>();

// 要素を後ろに追加していく
for (int i = 0; i <= 9; i++) {
  list.Add(i.ToString());
}

// 要素を指定した位置(5番目)に挿入する
list.Insert(4, "Inserted String.");

// 要素を列挙していく
foreach(var item in list) {
  Console.WriteLine(item);
}

// 現在の容量確認
Console.WriteLine(list.Count.ToString());

// 最大容量の確認
Console.WriteLine(list.Capacity.ToString());

// 特定の要素を表示
Console.WriteLine(list[6]);

Dictionaryクラス

キーと値をペアで格納できるクラス。
順序は保証されないが、キーを指定すればその値を取得することができる。
foreachでキーと値を得るのにとても便利。

ソース例

// 初期宣言
var dict = new Dictionary<string, string>();

// キーとバリュー(値)の追加
dict.Add("key1", "value1");
dict.Add("key2", "value2");

// キーとバリューを列挙
foreach(var pair in dict) {
  Console.WriteLine(
    pair.Key
      + "は" 
      + pair.Value
  );
}

// 任意のキーのバリューを表示
string value = dict["key1"];


その他知っとくと良いかもしれないクラス

・Hashsetクラス
とにかく要素をいれるクラス。
順番も一切保証されないが、とにかく入れて検索!といった用途には便利。
要素の重複はできない。
検索は非常に高速。

・QueとStackクラス
順序を保証して出し入れできるクラス。
キューは先入先出・スタックは後入先出。
上記の制約があるので、Listのほうが自由度はある。


ところで、コレクションはどうやって実現されているかといえば
ただ余分に配列を確保して、足りなくなったら新たに配列を作って元の配列をコピーしている模様。
これをやり続けると、動作が重くなる。
そこで、そのリスクを避けるため、あらかじめ初期容量を指定することもできる。

// 容量を3つ用意する
var list = new List<string>(3);


参考:Listを使わずに、静的に配列を宣言して、リサイズする方法。

string[] str = new string[1];

for (int i = 0; i < 5; i++) {
  // 配列を拡張
  Array.Resize(ref str, i + 1);
  // 文字を挿入
  str[0] = "test" + i.ToString();
}

// 特定文字の表示
Console.WriteLine(str[2]);


参考書籍(雑誌)

日経ソフトウエア 2012年 12月号 [雑誌]

参考リンク
ジェネリック・クラスで変わるC#とVBのコレクション - @IT