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

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

配列の長さを変更するには、VBでは「ReDim Preserve」を使うと簡単にできます。ここでは「ReDim Preserve」を使わずに配列の長さを変更する方法を紹介します。

.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(intArray, 10)
C#
コードを隠すコードを選択
//要素数5の配列
int[] intArray = { 0, 1, 2, 3, 4 };
//要素数を10に増やす
Array.Resize(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;

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

.NET Framework 2.0以降ではArray.Copyメソッドの代わりにBuffer.BlockCopyメソッドを使用することができ、この方法が最速であるようです。ただしBuffer.BlockCopyメソッドはプリミティブ型(Boolean、Char、SByte、Byte、Int16、UInt16、Int32、UInt32、Int64、UInt64、IntPtr、UIntPtr、Single、Double)の配列だけに使用できます。Buffer.BlockCopyメソッドについてさらに詳しくは、「複数の配列をマージする」をご覧ください。

VB.NET
コードを隠すコードを選択
'要素数5の配列
Dim intArray As Integer() = {0, 1, 2, 3, 4}
'要素数10の配列を作る 
Dim newArray As Integer() = New Integer(9) {}
'型のサイズを取得する(Int32の場合は 4)
Dim typeSize As Integer = System.Runtime.InteropServices.Marshal.SizeOf( _
    intArray.[GetType]().GetElementType())
'配列の要素をコピーする 
Buffer.BlockCopy(intArray, 0, newArray, 0, _
                Math.Min(intArray.Length, newArray.Length) * typeSize)
'できた配列をintArrayに戻す 
intArray = newArray
C#
コードを隠すコードを選択
//要素数5の配列
int[] intArray = { 0, 1, 2, 3, 4 };
//要素数10の配列を作る
int[] newArray = new int[10];
//型のサイズを取得する(Int32の場合は 4)
int typeSize = System.Runtime.InteropServices.Marshal.SizeOf(
    intArray.GetType().GetElementType());
//配列の要素をコピーする
Buffer.BlockCopy(intArray, 0, newArray, 0,
    Math.Min(intArray.Length, newArray.Length) * typeSize);
//できた配列をintArrayに戻す
intArray = newArray;

コレクションを使用する

配列の大きさを頻繁に変更するのであれば、コレクション(List(T)クラスArrayListクラスなど)の利用を検討してください。コレクションであれば、要素の追加、挿入、削除などが簡単にできます。

また、配列からコレクション、コレクションから配列の変換も簡単にできますので、これを利用して配列のサイズを変更することもできます。

下の例では、配列をコレクションに変換してから、要素を追加、挿入、削除して、また配列に戻しています。

VB.NET
コードを隠すコードを選択
'要素数5の配列
Dim intArray As Integer() = {0, 1, 2, 3, 4}

'配列をコレクションに変換する
Dim intList As New System.Collections.Generic.List(Of Integer)(intArray)
'.NET Framework 1.1以前ならば、次のようにする
'Dim intList As New System.Collections.ArrayList(intArray)
'末尾に5を追加する
intList.Add(5)
'先頭に-1を挿入する
intList.Insert(0, -1)
'インデックスが1(つまり、2番目)の要素を削除する
intList.RemoveAt(1)

'コレクションを配列に変換する
intArray = intList.ToArray()
'.NET Framework 1.1以前ならば、次のようにする
'intArray = DirectCast(intList.ToArray(GetType(Integer)), Integer())

'配列は、{ -1, 1, 2, 3, 4, 5 }となる
C#
コードを隠すコードを選択
//要素数5の配列
int[] intArray = { 0, 1, 2, 3, 4 };

//配列をコレクションに変換する
System.Collections.Generic.List<int> intList =
    new System.Collections.Generic.List<int>(intArray);
//.NET Framework 1.1以前ならば、次のようにする
//System.Collections.ArrayList intList =
//    new System.Collections.ArrayList(intArray);
//末尾に5を追加する
intList.Add(5);
//先頭に-1を挿入する
intList.Insert(0, -1);
//インデックスが1(つまり、2番目)の要素を削除する
intList.RemoveAt(1);

//コレクションを配列に変換する
intArray = intList.ToArray();
//.NET Framework 1.1以前ならば、次のようにする
//intArray = (int[])intList.ToArray(typeof(int));

//配列は、{ -1, 1, 2, 3, 4, 5 }となる

LINQを使用する

LINQを使えば、配列のようなシーケンスを簡単に扱うことができます。LINQでできることはあまりに多いため、ここではEnumerable.Takeメソッドを使って配列の長さを短くする例だけを示します。このメソッドは、.NET Framework 3.5以降でサポートされています。

VB.NET
コードを隠すコードを選択
'要素数5の配列
Dim intArray As Integer() = {0, 1, 2, 3, 4}
'配列の長さを1つ短くする
intArray = intArray.Take(intArray.Length - 1).ToArray()
'配列は、{ 0, 1, 2, 3 }となる
C#
コードを隠すコードを選択
//要素数5の配列
int[] intArray = { 0, 1, 2, 3, 4 };
//配列の長さを1つ短くする
intArray = intArray.Take(intArray.Length - 1).ToArray();
//配列は、{ 0, 1, 2, 3 }となる

バイト型配列の代わりにMemoryStreamクラスを使用する

バイト型配列の場合、配列の大きさを頻繁に変更するならば、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();
  • 履歴:
  • 2007/9/24 Array.Resizeメソッドを使った方法を追加。
  • 2009/8/27 Buffer.BlockCopyメソッドを使った方法を追加。
  • 2013/8/25 コレクションを使用する方法にサンプルを追加など。
  • 2015/2/2 コレクションのサンプルで、ArrayListの代わりにListを使うように変更。LINQを使った方法を追加。

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

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。