DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

C#でReDim Preserveの代わりになるものは?
配列の大きさを変える

VBでは、「ReDim Preserve」を使用して配列の長さを変更することができます。C#で配列の長さを変更するにはどのようにしたらよいでしょうか?

.NET Framework 2.0以降で、Array.Resizeメソッドを使用する

.NET Framework 2.0以降では、Array.Resizeメソッドが"ReDim Preserve"の代わりになります。

以下に、整数型配列の要素数を5から10に増やす例を示します。

VB.NET
コードを隠すコードを選択
'要素数5の配列を作る 
Dim intArray As Integer() = {0, 1, 2, 3, 4}
'要素を10にする 
Array.Resize(Of Integer)(intArray, 10)
C#
コードを隠すコードを選択
//要素数5の配列を作る
int[] intArray = { 0, 1, 2, 3, 4 };
//要素を10にする
Array.Resize<int>(ref intArray, 10);

Array.Copyメソッドを使用する

.NET Framework 1.1以前でArray.Resizeメソッドが使えない時は、自分でなんとかするしかありません。順当だと思われるのは、変更したいサイズの配列を新たに作成し、その配列に要素をコピーするという方法です。

Array.Resizeメソッドは内部でArray.Copyメソッドを呼び出しているため、結局はどちらも同じことを行っています。

次に要素数を5から10に増やす例を示します。

VB.NET
コードを隠すコードを選択
'要素数5の配列を作る 
Dim intArray As Integer() = {0, 1, 2, 3, 4}
'要素数10の配列を作る 
Dim newArray As Integer() = New Integer(9) {}
'配列の要素をコピーする 
Array.Copy(intArray, newArray, Math.Min(intArray.Length, newArray.Length))
'できた配列をintArrayに戻す 
intArray = newArray
C#
コードを隠すコードを選択
//要素数5の配列を作る
int[] intArray = {0, 1, 2, 3, 4};
//要素数10の配列を作る
int[] newArray = new int[10];
//配列の要素をコピーする
Array.Copy(intArray, newArray, Math.Min(intArray.Length, newArray.Length));
//できた配列をintArrayに戻す
intArray = newArray;

バイト型配列の場合

バイト型配列の場合、配列の大きさを頻繁に変更するならば、MemoryStreamオブジェクトを使うと便利です。MemoryStreamオブジェクトのコンストラクタに基になるバイト型配列を指定できますが、この場合、指定されたバイト型配列のサイズ以上の容量にすることが出来なくなります。

MemoryStreamオブジェクトを使えば、下記の例のように、簡単にバイト型配列を追加したり、サイズを変更することができます。

VB.NET
コードを隠すコードを選択
'MemoryStreamオブジェクトの作成 
Dim ms As New System.IO.MemoryStream()

'バイト型配列をMemoryStreamに追加する 
Dim bs1 As Byte() = New Byte() {0, 1, 2, 3, 4}
ms.Write(bs1, 0, bs1.Length)

'さらに追加する 
Dim bs2 As Byte() = New Byte() {5, 6, 7}
ms.Write(bs2, 0, bs2.Length)

'MemoryStreamの大きさを変更する 
ms.SetLength(10)

'MemoryStreamの内容をバイト型配列に変換する 
Dim bs As Byte() = ms.ToArray()

'閉じる 
ms.Close()
C#
コードを隠すコードを選択
//MemoryStreamオブジェクトの作成
System.IO.MemoryStream ms = new System.IO.MemoryStream();

//バイト型配列をMemoryStreamに追加する
byte[] bs1 = new byte[] {0, 1, 2, 3, 4};
ms.Write(bs1, 0, bs1.Length);

//さらに追加する
byte[] bs2 = new byte[] {5, 6, 7};
ms.Write(bs2, 0, bs2.Length);

//MemoryStreamの大きさを変更する
ms.SetLength(10);

//MemoryStreamの内容をバイト型配列に変換する
byte[] bs = ms.ToArray();

//閉じる
ms.Close();

.NET Framework 2.0以降で、Buffer.BlockCopyメソッドを使用する

.NET Framework 2.0以降ではBuffer.BlockCopyメソッドを使用することができ、この方法が最速であるようです。ただしBuffer.BlockCopyメソッドはプリミティブ型(Boolean、Char、SByte、Byte、Int16、UInt16、Int32、UInt32、Int64、UInt64、IntPtr、UIntPtr、Single、Double)の配列だけに使用できます。

VB.NET
コードを隠すコードを選択
'要素数5の配列を作る 
Dim intArray As Integer() = {0, 1, 2, 3, 4}
'要素数10の配列を作る 
Dim newArray As Integer() = New Integer(9) {}
'配列の要素をコピーする 
'Int32の大きさは4バイトなので、長さに4を掛けている 
Buffer.BlockCopy(intArray, 0, newArray, 0, _
                Math.Min(intArray.Length, newArray.Length) * 4)
'できた配列をintArrayに戻す 
intArray = newArray
C#
コードを隠すコードを選択
//要素数5の配列を作る
int[] intArray = { 0, 1, 2, 3, 4 };
//要素数10の配列を作る
int[] newArray = new int[10];
//配列の要素をコピーする
//Int32の大きさは4バイトなので、長さに4を掛けている
Buffer.BlockCopy(intArray, 0, newArray, 0,
    Math.Min(intArray.Length, newArray.Length) * 4);
//できた配列をintArrayに戻す
intArray = newArray;

コレクションを使用する

配列の大きさを頻繁に変更するのであれば、コレクション(List(T)クラスArrayListクラスなど)の利用を検討してください。

  • 履歴:
  • 2007/9/24 Array.Resizeメソッドを使った方法を追加。
  • 2009/8/27 Buffer.BlockCopyメソッドを使った方法を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。