配列

配列の作成

1次元配列

1 次元配列 (C# プログラミング ガイド) | MSDN

// 1次元配列の宣言
int[] array1 = new int[5];

// 初期化を伴う宣言
int[] array2 = new int[] { 1, 2, 3 };
int[] array3 = new[] { 1, 2, 3 };

// ... 代替の構文
int[] array4 = { 1, 2, 3 };

newを省略する代替の構文は、宣言時にのみ使用できます。

int[] array2;
array2 = new int[] { 1, 2, 3 }; // OK
array2 = new[] { 1, 2, 3 };     // OK

int[] array4;
array4 = { 1, 2, 3 }; // エラー CS1525 '{' は無効です。

初期化しない場合、値型は既定値に、参照型はnullに初期化されます。

int[] p1 = new int[10];         // 値型 (Int32構造体)
Point[] p2 = new Point[10];     // 値型 (Point構造体)
MyClass[] p3 = new MyClass[10]; // 参照型 (クラス)

Console.Write(p1[0]); // 0
Console.Write(p2[0]); // {X = 0 Y = 0}
Console.Write(p3[0]); // null

要素数を負数とすると、OverflowException例外が発生します。

int size = -1;
int[] p = new int[size]; // System.OverflowException はハンドルされませんでした。「算術演算の結果オーバーフローが発生しました。」

多次元配列 (Multidimensional Array) / n次元配列 (矩形配列)

多次元配列 (C# プログラミング ガイド) | MSDN

// 2次元配列の宣言
int[,] array1 = new int[2, 3]; // 2行3列の配列

// 初期化を伴う宣言
int[,] array2 = { { 1, 2, 3 }, { 4, 5, 6 } };

// 2次元配列へのアクセス
Console.Write(array2[1, 2]); // 6
// 3次元配列の宣言
int[,,] array3 = new int[2, 3, 4];
Console.Write( array3.Rank ); // 3

CreateInstance()を用いて、次のように作成することもできます。この方法では参照型の要素はnullに、値型のそれは0に初期化されます。

int[,]  a2 = (int[,]) Array.CreateInstance(typeof(int), 2, 3);
int[,,] a3 = (int[,,])Array.CreateInstance(typeof(int), 2, 3, 4);
Array.CreateInstance メソッド (Type, Int32, Int32) (System) | MSDN

次元数と要素数

int[,] array1 = new int[2, 3];

Console.Write( array1.Rank );   // 次元数:2
Console.Write( array1.Length ); // 要素の総数:6

Console.Write( array1.GetLength(0) ); // 要素数:2
Console.Write( array1.GetLength(1) ); // 要素数:3

パフォーマンスの問題

CA1814: 複数次元の配列ではなくジャグ配列を使用します | MSDN

ジャグ配列 (Jagged Array) / 配列の配列

ジャグ配列とは配列を要素に持つ配列で、それぞれの要素の配列はサイズが異なっていても構いません。ジャグ配列 (C# プログラミング ガイド) | MSDN

// ジャグ配列の宣言
int[][] array1 = new int[3][];

//
array1[0] = new int[] { 1, 2, 3, 4 };
array1[1] = new int[] { 5, 6 };
array1[2] = new int[] { 7, 8, 9 };

// 初期化を伴う宣言
int[][] array2 = new int[][]
{
    new int[] { 1, 2, 3, 4 },
    new int[] { 5, 6 },
    new int[] { 7, 8, 9 }
};

// ジャグ配列へのアクセス
Console.Write( array2[2][1] ); // 8
// 3次元配列の宣言
int[][][] array3 = new int[2][][];

array3[0] = new int[2][];
array3[1] = new int[2][];

array3[0][0] = new int[] { 1, 2 };
array3[0][1] = new int[] { 3, 4 };

array3[1][0] = new int[] { 5, 6 };
array3[1][1] = new int[] { 7, 8 };

Console.Write(array3[0][0][1]); // 2
Console.Write(array3[0][1][0]); // 3
Console.Write(array3[1][0][0]); // 5

// 初期化を伴う宣言
int[][][] array4 = new int[][][]
{
    new int[][]
    {
        new int[] { 1, 2 },
        new int[] { 3, 4 },
    },
    new int[][]
    {
        new int[] { 5, 6 },
        new int[] { 7, 8 },
    }
};

ジャグ配列では次元数を表すRankはつねに1、すべての要素数を表すLengthは最初の配列の要素数となります。

int[][] array1 = new int[3][];
Console.Write( array1.Rank );         // 1
Console.Write( array1.Length );       // 3
Console.Write( array1.GetLength(0) ); // 3

array1[0] = new int[] { 1, 2 };

Console.Write( array1[0].Rank );         // 1
Console.Write( array1[0].Length );       // 2
Console.Write( array1[0].GetLength(0) ); // 2

メモリ不足による配列の生成の失敗

過度に大きなサイズの配列を生成しようとすると、OutOfMemoryException例外が発生します。32ビット アプリケーションでは1つのオブジェクトの上限が2GBで、64ビットも既定では2GBです。Remarks - OutOfMemoryException Class (System) | MSDN

byte[] a = new byte[1024 * 1024 * (1024 + 512)]; // System.OutOfMemoryException

この上限は、64ビット環境ではgcAllowVeryLargeObjectsを指定することで拡大できます。<gcAllowVeryLargeObjects> 要素 | MSDN

Arrayクラス

CLRにおける配列の基本クラスです。

int[] array1 = new int[5];
Array array2 = Array.CreateInstance(typeof(int), 5);

Type type1 = array1.GetType(); // System.Int32[]
Type type2 = array2.GetType(); // System.Int32[]

実装しているインターフェイス

[SerializableAttribute]
[ComVisibleAttribute(true)]
public abstract class Array : ICloneable, IList, ICollection,
    IEnumerable, IStructuralComparable, IStructuralEquatable
構文 - Array クラス (System) | MSDN
  • ICloneable
  • IList
  • ICollection
  • IEnumerable
  • IStructuralComparable
  • IStructuralEquatable

プロパティ

プロパティ 内容
IsFixedSize Arrayが固定サイズかどうか
IsReadOnly Arrayが読み取り専用かどうか
IsSynchronized Arrayへのアクセスが同期されている (スレッドセーフである) かどうか
Length Arrayのすべての次元内の要素の総数
LongLength Arrayのすべての次元内の要素の総数 (64ビット整数)
Rank Arrayのランク (次元数) を取得する。たとえば1次元配列は1で、2次元は2
SyncRoot Arrayへのアクセスを同期するために使用できるオブジェクト
プロパティ - Array クラス (System) | MSDN

メソッド

主要なメソッド
  名前 説明
作成 CreateInstance(Type, Int32) Typeと長さを指定して、0から始まるインデックスを持つ1次元の配列を作成する
CreateInstance(Type, Int32, Int32) Typeと次元の長さを指定して、0から始まるインデックスを持つ2次元の配列を作成する
CreateInstance(Type, Int32, Int32, Int32) Typeと次元の長さを指定して、0から始まるインデックスを持つ3次元の配列を作成する
CreateInstance(Type, Int32[]) Typeと次元の長さを指定して、0から始まるインデックスを持つ多次元の配列を作成する
Empty<T>() 空の配列を返す
初期化 Initialize() 値型の既定のコンストラクターを呼び出し、この値型の各要素を初期化する
Clear(Array, Int32, Int32) 配列内にある要素の範囲を、各要素の型の既定値に設定する
複製 Clone() Arrayの簡易コピーを作成する
CopyTo(Array, Int32) 1次元配列のすべての要素を、指定の1次元配列にコピーする
Copy(Array, Array, Int32) 他の配列に、指定範囲の要素をコピーする
ConstrainedCopy(Array, Int32, Array, Int32, Int32) 他の配列に、指定範囲の要素をコピーする。コピーが完全に成功しないならば、変更が適用されないことが保証される
AsReadOnly<T>(T[]) 指定の配列をラップする、読み取り専用のラッパーを作成する
要素数 GetLength(Int32) 指定の次元にある要素の数を表す、32ビット整数を取得する
GetLongLength(Int32) 指定の次元にある要素の数を表す、64ビット整数を取得する
値の取得 GetValue(Int32) 1次元の配列内の、指定位置にある値を取得する
GetValue(Int32, Int32) 2次元の配列内の、指定位置にある値を取得する
GetValue(Int32, Int32, Int32) 3次元の配列内の、指定位置にある値を取得する
GetValue(Int32[]) 多次元の配列内の、指定位置にある値を取得する
値の設定 SetValue(Object, Int32) 1次元の配列内の指定位置にある要素に、値を設定する
SetValue(Object, Int32, Int32) 2次元の配列内の指定位置にある要素に、値を設定する
SetValue(Object, Int32, Int32, Int32) 3次元の配列内の指定位置にある要素に、値を設定する
SetValue(Object, Int32[]) 多次元の配列内の指定位置にある要素に、値を設定する
検索 FindAll<T>(T[], Predicate<T>) 指定条件に一致する、すべての要素を取得する
Find<T>(T[], Predicate<T>) 指定条件に一致する要素を検索し、最もインデックスの小さい要素を返す
FindLast<T>(T[], Predicate<T>) 指定条件に一致する要素を検索し、最もインデックスの大きい要素を返す
FindIndex<T>(T[], Predicate<T>) 指定条件に一致する要素を検索し、最もインデックスの小さい要素のインデックスを返す
FindLastIndex<T>(T[], Predicate<T>) 指定条件に一致する要素を検索し、最もインデックスの大きい要素のインデックスを返す
IndexOf(Array, Object) 指定のオブジェクトを検索し、1次元の配列でそのオブジェクトが最初に見つかった位置のインデックスを返す
LastIndexOf(Array, Object) 指定のオブジェクトを検索し、1次元の配列でそのオブジェクトが最後に見つかった位置のインデックスを返す
BinarySearch(Array, Object) 1次元の並べ替え済み配列全体の中から、特定の要素を検索する
Exists<T>(T[], Predicate<T>) 指定の配列に、指定条件に一致する要素が含まれているかどうかを判断する
TrueForAll<T>(T[], Predicate<T>) 配列内のすべての要素が、指定条件に一致するかどうかを調べる
並べ替え Sort(Array) Arrayの各要素のIComparable実装を使用して、1次元配列全体の要素を並べ替える
Sort(Array, IComparer) 1次元の配列内の要素を、指定のIComparerを使用して並べ替える
Sort(Array, Array, IComparer) 2つの1次元配列オブジェクト (一方のオブジェクトがキーを格納し、他方のオブジェクトがそれらに対応する項目を格納する) を、最初の配列内のキーに基づき、指定のIComparerを使用して並べ替える
Reverse(Array) 1次元の配列内の、要素のシーケンスを反転させる
変換 ConvertAll<TInput, TOutput>(TInput[], Converter<TInput, TOutput>) ある型の配列を、別の型の配列に変換する
Resize<T>(T[], Int32) 1次元の配列の要素数を、指定した新しいサイズに変更する
その他 ForEach<T>(T[], Action<T>) 指定の配列内の各要素に対して、指定された処理を実行する
GetLowerBound(Int32) 配列内の指定の次元の、最初の要素のインデックスを取得する
GetUpperBound(Int32) 配列内の指定の次元の、最後の要素のインデックスを取得する
メソッド - Array クラス (System) | MSDN

配列の複製

配列を複製できるメソッドは3つあり、これらは複製できる範囲と適用可能な次元に違いがあります。

メソッド 複製範囲 適用可能な次元
Clone() すべての要素 任意の次元
CopyTo() 指定位置から末尾までの要素 1次元のみ
Copy() 指定位置から末尾までの要素、または指定位置から指定数の要素 任意の次元

これらのメソッドではすべて、シャローコピー (Shallow copy) で処理されます。c# - Deep Copy with Array - Stack Overflow

public object Clone()
Array.Clone メソッド (System) | MSDN
public void CopyTo(
    Array array, // コピー先の配列
    int index    // コピーを開始するインデックス
)
Array.CopyTo メソッド (Array, Int32) (System) | MSDN Array.CopyTo メソッド (System) | MSDN

コピー先の要素が不足するとArgumentExceptionが発生し、充足ならば元の値が残ります。

public static void Copy(
    Array sourceArray,      // コピー元の配列
    Array destinationArray, // コピー先の配列
    int length              // コピーする要素の数
)
Array.Copy メソッド (Array, Array, Int32) (System) | MSDN Array.Copy メソッド (System) | MSDN
public static void Copy(
    Array sourceArray,      // コピー元の配列
    int sourceIndex,        // コピーを開始するインデックス
    Array destinationArray, // コピー先の配列
    int destinationIndex,
    int length
)
Array.Copy メソッド (Array, Int32, Array, Int32, Int32) (System) | MSDN

多次元配列をコピーするときには、すべての要素が1次元に並んでいると見なしてsourceIndexなどのインデックスを指定します。

サンプルコード
class MyClass
{
    public int data;
    public MyClass(int data) { this.data = data; }
}
Clone()
MyClass[] src = { new MyClass(1), new MyClass(2) };

MyClass[] dest = (MyClass[])src.Clone();

src[0].data = 3;
Console.Write(dest[0].data); // 3
CopyTo()
MyClass[] src = { new MyClass(1), new MyClass(2) };

MyClass[] dest = new MyClass[src.Length];
src.CopyTo(dest, 0);

src[0].data = 3;
Console.Write(dest[0].data); // 3
Copy()
MyClass[] src = { new MyClass(1), new MyClass(2) };

MyClass[] dest = new MyClass[src.Length];
Array.Copy(src, dest, src.Length);

src[0].data = 3;
Console.Write(dest[0].data); // 3
多次元配列の複製

Clone()とCopy()で、1次元配列と同様に複製できます。一方でCopyTo()は多次元に対応しないため、例外が発生します。

int[,] src = { { 1, 2, 3 }, { 4, 5, 6 } };

// Clone()
int[,] dest1 = (int[,])src.Clone();

// CopyTo()
int[,] dest2 = new int[src.GetLength(0), src.GetLength(1)];
src.CopyTo(dest2, 0); // System.ArgumentException 要求されたアクションに対しては、1 次元配列のみがサポートされます。

// Copy()
int[,] dest3 = new int[src.GetLength(0), src.GetLength(1)];
Array.Copy(src, dest3, src.Length);
ジャグ配列

ジャグ配列の要素は配列のため、シャローコピーにより参照がコピーされることで、コピー先の配列への変更がコピー元へ影響します。

int[][] src = new int[][]
{
    new int[] { 1, 2, 3 },
    new int[] { 4, 5, 6 }
};

int[][] dest = (int[][])src.Clone();

dest[1][1] = 10;          // コピー先の配列を変更
Console.Write(src[1][1]); // 10 (コピー元の配列へ影響する)
// 多次元配列 の場合
int[,] src = { { 1, 2, 3 }, { 4, 5, 6 } };

int[,] dest = (int[,])src.Clone();

dest[1, 1] = 10;          // コピー先の配列を変更
Console.Write(src[1, 1]); // 5 (コピー元の配列は影響されない)
2次元配列から1次元配列への複製

Copy()では「System.RankException 指定された配列の次元数は同じでなければなりません。」として異なる次元へ複製できないため、Buffer.BlockCopy()でバイト単位で複製します。c# - Does Array.Copy work with multidimensional arrays? - Stack Overflow

int[,] src = { { 1, 2, 3 }, { 4, 5, 6 } }; // コピー元の2次元配列

int[] dest = new int[src.Length]; // コピー先の1次元配列
int count = src.GetLength(1) * sizeof(int);

for (int i = 0; i < src.Rank; i++)
{
    int offset = count * i;
    Buffer.BlockCopy(src, offset, dest, offset, count);
}

一方でジャグ配列はその要素が配列のため、Copy()で処理できます。

int[][] src = new int[3][]; // コピー元の2次元配列
src[0] = new int[] { 1, 2, 3, 4 };
src[1] = new int[] { 5, 6 };
src[2] = new int[] { 7, 8, 9 };

int[] dest = new int[9]; // コピー先の1次元配列
Array.Copy(src[0], 0, dest, 0, 4);
Array.Copy(src[1], 0, dest, 4, 2);
Array.Copy(src[2], 0, dest, 6, 3);

汎用的には次のようにします。

int sum = 0;
for (int i = 0; i < src.Length; i++)
{
    sum += src[i].Length;
}
int[] dest = new int[sum];

for (int i = 0, offset = 0; i < src.Length; i++)
{
    int length = src[i].Length;
    Array.Copy(src[i], 0, dest, offset, length);

    offset += length;
}

要素の検索

IndexOf()

指定オブジェクトに一致する要素を検索できます。

public static int IndexOf(
    Array array, // 検索対象の1次元配列
    object value // 検索するオブジェクト
)
Array.IndexOf メソッド (Array, Object) (System) | MSDN

見つかった場合は一致した最初の要素のインデックス、さもなくば配列のインデックスの下限から-1したインデックスが返されます。

int[] a = new int[] { 1, 2, 3, 4, 5 };

int r1 = Array.IndexOf(a, 3);  // 2
int r2 = Array.IndexOf(a, 10); // -1 (インデックスの下限0から-1した値)

比較はObject.Equals()メソッドで行われます。これをそのオブジェクトのEquals()で行いたいならば、IndexOf<T>を用います。この場合、比較はT.Equals()で行われます。

public static int IndexOf<T>(
    T[] array,
    T value
)
Array.IndexOf(T) メソッド (T[], T) (System) | MSDN
int[] a = new int[] { 1, 2, 3 };
int r = Array.IndexOf<int>(a, 3); // 2

List<T>.IndexOf(T)

Find()

指定条件に一致する要素を検索できます。

public static T Find<T>(
    T[] array,
    Predicate<T> match
)
Array.Find(T) メソッド (T[], Predicate(T)) (System) | MSDN

見つかった場合は一致した最初の要素、さもなくば型Tの既定値が返されます。

void MyClass()
{
    int[] a = new int[] { 1, 2, 3, 4, 5 };

    int r1 = Array.Find(a, Predicate); // 4
}

bool Predicate(int x)
{
    return 3 < x;
}

ラムダ式を用いると、以下のようにも記述できます。

int r2 = Array.Find(a, (x) => { return 3 < x; }); // 4
int r3 = Array.Find(a,  x  =>          3 < x   ); // 4

int r4 = Array.Find(a,  x  =>         10 < x   ); // 0 (0はintの既定値)

IndexOf()とは異なり、Find()が返すのはインデックスではなく要素です。

string[] str = new string[] { "a", "b", "c" };
string result = Array.Find(str, (x) => { return x == "b"; }); // "b"

要素の並べ替え

Sort()

並べ替えの方法やその範囲によって、下表のようにオーバーロードされています。

Sort(Array)
Sort(Array, Array)
Sort(Array, Array, IComparer)
Sort(Array, Array, Int32, Int32)
Sort(Array, Array, Int32, Int32, IComparer)
Sort(Array, IComparer)
Sort(Array, Int32, Int32)
Sort(Array, Int32, Int32, IComparer)
Sort<T>(T[])
Sort<T>(T[], Comparison<T>)
Sort<T>(T[], IComparer<T>)
Sort<T>(T[], Int32, Int32)
Sort<T>(T[], Int32, Int32, IComparer<T>)
Sort<TKey, TValue>(TKey[], TValue[])
Sort<TKey, TValue>(TKey[], TValue[], IComparer<TKey>)
Sort<TKey, TValue>(TKey[], TValue[], Int32, Int32)
Sort<TKey, TValue>(TKey[], TValue[], Int32, Int32, IComparer<TKey>)
Array.Sort メソッド (System) | MSDN
int[] a1 = { 3, 4, 6, 2, 4, 1 };
Array.Sort(a1);
// 1, 2, 3, 4, 4, 6

int[] a2 = { 1, 2, 3, 4, 5 };
Array.Sort(a2, (x, y) => { return y - x; });
// 5, 4, 3, 2, 1

int[] a3 = { 1, 2, 3, 4, 5 };
Array.Sort(a3, (x, y) => { return (x == 3) ? -1 : 0; });
// 3, 1, 2, 4, 5

パーティションのサイズによって、使用されるアルゴリズムが異なります。Remarks - Array.Sort Method (Array, IComparer) (System) | MSDN

// 要素数16
int[] a4 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
Array.Sort(a4, (x, y) => { return 0; });
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

Array.Sort(a4, (x, y) => { return -1; });
// 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1

a4 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
Array.Sort(a4, (x, y) => { return (x == 5) ? -1 : 0; });
// 5, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
// 要素数17
int[] a5 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
Array.Sort(a5, (x, y) => { return 0; });
// 1, 15, 14, 13, 12, 11, 10, 16, 9, 7, 6, 5, 4, 3, 2, 8, 17

a5 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
Array.Sort(a5, (x, y) => { return -1; }); // System.ArgumentExceptionが発生
// HResult : -2147024809 (0x80070057)
// IComparer.Compare() メソッドから矛盾する結果が返されたため、並べ替えできません。値をそれ自体と比較したときに等しい結果にならないか、またはある値を別の値と繰り返し比較したときに異なる結果が生じます。

a5 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
Array.Sort(a5, (x, y) => { return (x == 5) ? -1 : 0; });
// 5, 1, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 16, 17
// 要素数18
int[] a6 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
Array.Sort(a6, (x, y) => { return 0; });
// 1, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 17, 18

Reverse()

public static void Reverse(
    Array array,
    int index,
    int length
)
Array.Reverse メソッド (Array, Int32, Int32) (System) | MSDN
int[] array = new int[] { 1, 2, 3, 4, 5, 6 };
Array.Reverse(array, 1, 4); // { 1, 5, 4, 3, 2, 6 }

要素の変換

ConvertAll<TInput, TOutput>()
public static TOutput[] ConvertAll<TInput, TOutput>(
    TInput[] array,
    Converter<TInput, TOutput> converter
)
Array.ConvertAll(TInput, TOutput) Method (TInput[], Converter(TInput, TOutput)) (System) | MSDN
public delegate TOutput Converter<in TInput, out TOutput>(
    TInput input
)
Converter(TInput, TOutput) Delegate (System) | MSDN
static void Main()
{
    double[] src = new double[] { 1.5, 2.5, 3.5 };

    // 方法1:
    Converter<double, int> convert = new Converter<double, int>(DoubleToInt);
    int[] dst1 = Array.ConvertAll<double, int>(src, convert);

    // 方法2:一時変数をインライン化し、変換メソッドをdelegateで記述
    int[] dst2 = Array.ConvertAll(src, new Converter<double, int>(delegate (double x) { return (int)x; }));

    // 方法3:delegateをラムダ式で記述
    int[] dst3 = Array.ConvertAll(src, new Converter<double, int>((x) => { return (int)x; }));

    // 方法4:Convertクラスのメソッドで記述
    int[] dst4 = Array.ConvertAll(src, Convert.ToInt32);
}

static int DoubleToInt(double x)
{
    return (int)x;
}
c# - What is the actual use of Array.ConvertAll compared to e.g. looping through the array via foreach? - Stack Overflow

たとえばbyte配列からshort配列へは、次のようにも変換できます。bytearray - Convert byte array to short array in C# - Stack Overflow

byte[] src = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
short[] dst = new short[src.Length / 2];

Buffer.BlockCopy(src, 0, dst, 0, src.Length);

Console.WriteLine("{0:x4}", dst[0]); // 0201
Console.WriteLine("{0:x4}", dst[1]); // 0403
Console.WriteLine("{0:x4}", dst[2]); // 0605

ForEach<T>(T[], Action<T>)

public static void ForEach<T>(
    T[] array,
    Action<T> action
)
Array.ForEach(T) メソッド (T[], Action(T)) (System) | MSDN

ListのForEach()とは異なり、これは静的メソッドです。

int[] a = new int[] { 1, 2, 3 };

//
Array.ForEach(a, delegate (int x)
{
    Console.Write(x);
});

// ラムダ式。上に同じ
Array.ForEach(a, x => Console.Write(x));

// 上に同じ
Array.ForEach(a, Console.Write);

ArrayListクラス

必要に応じてサイズが動的に拡大される配列です。

ArrayListの要素はObject型であり、要素に追加するたびにボックス化されます。この処理はパフォーマンスに影響するため、可能ならばList<T>を用いるべきです。ArrayListとListの違いとは?[C#/VB]:.NET TIPS - @IT 山本康彦 (2017/10/25)

ArrayList arrayList = new ArrayList();
arrayList.Add(5);
arrayList.Add("A");

実装しているインターフェイス

[SerializableAttribute]
[ComVisibleAttribute(true)]
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
構文 - ArrayList クラス (System.Collections) | MSDN
  • IList
  • ICollection
  • IEnumerable
  • ICloneable

Bufferクラス

BlockCopy

public static void BlockCopy(
    Array src,     // コピー元の配列
    int srcOffset, // コピー元の配列の、コピーされる位置
    Array dst,     // コピー先の配列
    int dstOffset, // コピー先の配列の、コピーする位置
    int count      // コピーするバイト数
)
Buffer.BlockCopy(Array, Int32, Array, Int32, Int32) Method (System) | Microsoft Docs

foreachステートメント

IEnumerableを実装するため、ArrayやArrayListでもforeachを使えます。

int[] array = new int[] { 1, 2, 3 };
foreach (int x in array)
{
    Console.Write(x);
}
// 123

多次元配列

1次元と同様の方法で、すべての要素を反復処理できます。ただし1次元に配置されているかのように処理されるため、それが意図したものでなければforループで記述します。配列での foreach の使用 (C# プログラミング ガイド) | MSDN

int[,] array = { { 1, 2, 3 }, { 4, 5, 6 } };
foreach (int x in array)
{
    Console.Write(x);
}
// 123456

ジャグ配列

ジャグ配列の要素は配列のため、foreachをネストします。

int[][] array = new int[][]
{
    new int[] { 1, 2, 3, 4 },
    new int[] { 5, 6 }
};

foreach (int[] a in array)
{
    foreach (int x in a)
    {
        Console.Write(x);
    }
}
// 123456

参考

参考書

MSDN (Microsoft Developer Network) から検索