配列の長さを変更するには、VBでは「ReDim Preserve」を使うと簡単にできます。ここでは「ReDim Preserve」を使わずに配列の長さを変更する方法を紹介します。
.NET Framework 2.0以降では、Array.Resizeメソッドが"ReDim Preserve"の代わりになります。
以下に、整数型配列の要素数を5から10に増やす例を示します。
'要素数5の配列 Dim intArray As Integer() = {0, 1, 2, 3, 4} '要素数を10に増やす Array.Resize(intArray, 10)
//要素数5の配列 int[] intArray = { 0, 1, 2, 3, 4 }; //要素数を10に増やす Array.Resize(ref intArray, 10);
.NET Framework 1.1以前でArray.Resizeメソッドが使えない時は、自分でなんとかするしかありません。順当だと思われるのは、変更したいサイズの配列を新たに作成し、その配列に要素をコピーするという方法です。
Array.Resizeメソッドは内部でArray.Copyメソッドを呼び出しているため、結局はどちらも同じことを行っています。
次に要素数を5から10に増やす例を示します。
'要素数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
//要素数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以降ではArray.Copyメソッドの代わりにBuffer.BlockCopyメソッドを使用することができ、この方法が最速であるようです。ただしBuffer.BlockCopyメソッドはプリミティブ型(Boolean、Char、SByte、Byte、Int16、UInt16、Int32、UInt32、Int64、UInt64、IntPtr、UIntPtr、Single、Double)の配列だけに使用できます。Buffer.BlockCopyメソッドについてさらに詳しくは、「複数の配列をマージする」をご覧ください。
'要素数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
//要素数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クラスなど)の利用を検討してください。コレクションであれば、要素の追加、挿入、削除などが簡単にできます。
また、配列からコレクション、コレクションから配列の変換も簡単にできますので、これを利用して配列のサイズを変更することもできます。
下の例では、配列をコレクションに変換してから、要素を追加、挿入、削除して、また配列に戻しています。
'要素数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 }となる
//要素数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でできることはあまりに多いため、ここではEnumerable.Takeメソッドを使って配列の長さを短くする例だけを示します。このメソッドは、.NET Framework 3.5以降でサポートされています。
'要素数5の配列 Dim intArray As Integer() = {0, 1, 2, 3, 4} '配列の長さを1つ短くする intArray = intArray.Take(intArray.Length - 1).ToArray() '配列は、{ 0, 1, 2, 3 }となる
//要素数5の配列 int[] intArray = { 0, 1, 2, 3, 4 }; //配列の長さを1つ短くする intArray = intArray.Take(intArray.Length - 1).ToArray(); //配列は、{ 0, 1, 2, 3 }となる
バイト型配列の場合、配列の大きさを頻繁に変更するならば、MemoryStreamクラスを使うと便利です。MemoryStreamクラスのコンストラクタに基になるバイト型配列を指定できますが、そうすると、指定されたバイト型配列のサイズ以上の容量にすることが出来なくなります。
MemoryStreamオブジェクトを使えば、下記の例のように、簡単にバイト型配列を追加したり、サイズを変更することができます。
'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()
//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();