配列は、論理的に相互に関連する一連の値 ( 要素と呼ばれる) です。 たとえば、配列は、文法学校の各学年の学生の数で構成される場合があります。配列の各要素は、1 つの成績の学生の数です。 同様に、配列はクラスの学生の成績で構成される場合があります。配列の各要素は 1 つのグレードです。
個々の変数を使用して、各データ項目を格納することができます。 たとえば、アプリケーションで学生の成績を分析する場合、 englishGrade1
、 englishGrade2
など、学生の成績ごとに個別の変数を使用できます。この方法には、次の 3 つの主な制限があります。
- 設計時に、処理する必要があるグレードの数を正確に把握する必要があります。
- 多数の成績を処理すると、すぐに扱いにくくなります。 これにより、アプリケーションに重大なバグが発生する可能性が大幅に高くなります。
- 維持することは困難です。 追加する新しいグレードごとに、アプリケーションを変更、再コンパイル、再デプロイする必要があります。
配列を使用すると、これらの関連する値を同じ名前で参照し、 インデックス または 添字 と呼ばれる数値を使用して、配列内の位置に基づいて個々の要素を識別できます。 配列のインデックスの範囲は、0 から配列内の要素の合計数より 1 未満です。 Visual Basic 構文を使用して配列のサイズを定義する場合は、配列内の要素の合計数ではなく、最も大きいインデックスを指定します。 配列を 1 つの単位として操作でき、その要素を反復処理する機能により、デザイン時に含まれる要素の数を正確に把握する必要ができなくなります。
説明の前にいくつかの簡単な例:
' Declare a single-dimension array of 5 numbers.
Dim numbers(4) As Integer
' Declare a single-dimension array and set its 4 values.
Dim numbers = New Integer() {1, 2, 4, 8}
' Change the size of an existing array to 16 elements and retain the current values.
ReDim Preserve numbers(15)
' Redefine the size of an existing array and reset the values.
ReDim numbers(15)
' Declare a 6 x 6 multidimensional array.
Dim matrix(5, 5) As Double
' Declare a 4 x 3 multidimensional array and set array element values.
Dim matrix = New Integer(,) {{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}
' Declare a jagged array
Dim sales()() As Double = New Double(11)() {}
単純な配列内の配列要素
students
という名前の配列を作成して、文法学校の各学年の生徒数を格納してみましょう。 要素のインデックスの範囲は 0 から 6 です。 この配列の使用は、7 つの変数を宣言するよりも簡単です。
次の図は、 students
配列を示しています。 配列の各要素について:
要素のインデックスはグレードを表します (インデックス 0 は幼稚園を表します)。
要素に含まれる値は、その成績の学生の数を表します。
次の例には、配列を作成して使用する Visual Basic コードが含まれています。
Module SimpleArray
Public Sub Main()
' Declare an array with 7 elements.
Dim students(6) As Integer
' Assign values to each element.
students(0) = 23
students(1) = 19
students(2) = 21
students(3) = 17
students(4) = 19
students(5) = 20
students(6) = 22
' Display the value of each element.
For ctr As Integer = 0 To 6
Dim grade As String = If(ctr = 0, "kindergarten", $"grade {ctr}")
Console.WriteLine($"Students in {grade}: {students(ctr)}")
Next
End Sub
End Module
' The example displays the following output:
' Students in kindergarten: 23
' Students in grade 1: 19
' Students in grade 2: 21
' Students in grade 3: 17
' Students in grade 4: 19
' Students in grade 5: 20
' Students in grade 6: 22
この例では、次の 3 つの処理が行われます。
- 7 つの要素を持つ
students
配列を宣言します。 配列宣言の6
数は、配列内の最後のインデックスを示します。配列内の要素数より 1 小さい値です。 - 配列内の各要素に値が割り当てられます。 配列要素には、配列名を使用してアクセスし、個々の要素のインデックスをかっこで囲みます。
- 配列の各値が一覧表示されます。 この例では、
For
ステートメントを使用して、配列の各要素にインデックス番号でアクセスします。
前の例の students
配列は、1 つのインデックスを使用するため、1 次元配列です。 複数のインデックスまたは添字を使用する配列は 、多次元と呼ばれます。 詳細については、この記事の残りの部分と Visual Basic の配列ディメンションを参照してください。
配列の作成
配列のサイズは、いくつかの方法で定義できます。
配列を宣言するときにサイズを指定できます。
' Declare an array with 10 elements. Dim cargoWeights(9) As Double ' Declare a 24 x 2 array. Dim hourlyTemperatures(23, 1) As Integer ' Declare a jagged array with 31 elements. Dim januaryInquiries(30)() As String
New
句を使用して、配列の作成時に配列のサイズを指定できます。' Declare an array with 10 elements. Dim cargoWeights() As Double = New Double(9) {} ' Declare a 24 x 2 array. Dim hourlyTemperatures(,) As Integer = New Integer(23, 1) {} ' Declare a jagged array with 31 elements. Dim januaryInquiries()() As String = New String(30)() {}
既存の配列がある場合は、 ReDim
ステートメントを使用してサイズを再定義できます。
ReDim
ステートメントが配列内の値を保持することを指定することも、空の配列を作成することを指定することもできます。 次の例は、既存の配列のサイズを変更する ReDim
ステートメントのさまざまな使用方法を示しています。
' Assign a new array size and retain the current values.
ReDim Preserve cargoWeights(20)
' Assign a new array size and retain only the first five values.
ReDim Preserve cargoWeights(4)
' Assign a new array size and discard all current element values.
ReDim cargoWeights(15)
詳細については、 ReDim ステートメントを参照してください。
配列に値を格納する
Integer
型のインデックスを使用して、配列内の各場所にアクセスできます。 かっこで囲まれたインデックスを使用して、各配列の場所を参照することで、配列内の値を格納および取得できます。 多次元配列のインデックスは、コンマ (,) で区切られます。 配列ディメンションごとに 1 つのインデックスが必要です。
次の例は、配列内の値を格納および取得するいくつかのステートメントを示しています。
Module Example
Public Sub Main()
' Create a 10-element integer array.
Dim numbers(9) As Integer
Dim value As Integer = 2
' Write values to it.
For ctr As Integer = 0 To 9
numbers(ctr) = value
value *= 2
Next
' Read and sum the array values.
Dim sum As Integer
For ctr As Integer = 0 To 9
sum += numbers(ctr)
Next
Console.WriteLine($"The sum of the values is {sum:N0}")
End Sub
End Module
' The example displays the following output:
' The sum of the values is 2,046
配列リテラルを使用して配列を設定する
配列リテラルを使用すると、作成時に初期の値セットを配列に設定できます。 配列リテラルは、中かっこ ({}
) で囲まれたコンマ区切りの値のリストで構成されます。
配列リテラルを使用して配列を作成する場合は、配列型を指定するか、型推論を使用して配列の型を決定できます。 次の例は、両方のオプションを示しています。
' Array literals with explicit type definition.
Dim numbers = New Integer() {1, 2, 4, 8}
' Array literals with type inference.
Dim doubles = {1.5, 2, 9.9, 18}
' Array literals with explicit type definition.
Dim articles() As String = { "the", "a", "an" }
' Array literals with explicit widening type definition.
Dim values() As Double = { 1, 2, 3, 4, 5 }
型推論を使用する場合、配列の型はリテラル値の一覧の 主要な型 によって決まります。 主要な型は、配列内の他のすべての型が拡大できる型です。 この一意の型を特定できない場合、優先度の高い型は、配列内の他のすべての型を絞り込むことができる一意の型です。 これらの一意の型のどちらも決定できない場合、優先型は Object
。 たとえば、配列リテラルに指定された値のリストに Integer
型、 Long
型、および Double
型の値が含まれている場合、結果の配列は Double
型になります。
Integer
とLong
はDouble
にのみ拡大されるため、Double
が優先型です。 詳細については、「 拡大/縮小変換」を参照してください。
注
型の推論は、型メンバーのローカル変数として定義されている配列にのみ使用できます。 明示的な型定義がない場合、クラス レベルで配列リテラルで定義された配列は Object[]
型になります。 詳細については、「 ローカル型の推論」を参照してください。
前の例では、すべての配列リテラルがInteger
型であっても、Double
型の配列としてvalues
を定義しています。 配列リテラル内の値は、 Double
値に拡大できるため、この配列を作成できます。
また、入れ子になった配列リテラルを使用して、多次元配列を作成して設定することもできます。 入れ子になった配列リテラルには、結果の配列と一致する多数の次元が必要です。 次の例では、入れ子になった配列リテラルを使用して、整数の 2 次元配列を作成します。
' Create and populate a 2 x 2 array.
Dim grid1 = {{1, 2}, {3, 4}}
' Create and populate a 2 x 2 array with 3 elements.
Dim grid2(,) = {{1, 2}, {3, 4}, {5, 6}}
入れ子になった配列リテラルを使用して配列を作成および設定すると、入れ子になった配列リテラル内の要素の数が一致しない場合にエラーが発生します。 配列リテラルとは異なる次元数を持つ配列変数を明示的に宣言すると、エラーも発生します。
1 次元配列の場合と同様に、入れ子になった配列リテラルを含む多次元配列を作成する場合は、型推論に依存できます。 推論された型は、すべての入れ子レベルのすべての配列リテラル内のすべての値の主要な型です。 次の例では、Integer
型とDouble
の値からDouble[,]
型の 2 次元配列を作成します。
Dim arr = {{1, 2.0}, {3, 4}, {5, 6}, {7, 8}}
その他の例については、「 方法: Visual Basic で配列変数を初期化する」を参照してください。
配列の反復処理
配列を反復処理する場合は、配列内の各要素に、最も低いインデックスから最も高いもの、または最も高いものから最下位の要素にアクセスします。 通常は、 For..を使用します。次のステートメント または For Each...次のステートメント は、配列の要素を反復処理します。 配列の上限がわからない場合は、 Array.GetUpperBound メソッドを呼び出してインデックスの最大値を取得できます。 インデックスの最小値はほぼ常に 0 ですが、 Array.GetLowerBound メソッドを呼び出してインデックスの最小値を取得できます。
次の例では、 For...Next
ステートメントを使用して 1 次元配列を反復処理します。
Module IterateArray
Public Sub Main()
Dim numbers = {10, 20, 30}
For index = 0 To numbers.GetUpperBound(0)
Console.WriteLine(numbers(index))
Next
End Sub
End Module
' The example displays the following output:
' 10
' 20
' 30
次の例では、 For...Next
ステートメントを使用して多次元配列を反復処理します。
GetUpperBound メソッドには、ディメンションを指定するパラメーターがあります。
GetUpperBound(0)
は最初のディメンションの最も高いインデックスを返し、 GetUpperBound(1)
は 2 番目のディメンションの最も高いインデックスを返します。
Module IterateArray
Public Sub Main()
Dim numbers = {{1, 2}, {3, 4}, {5, 6}}
For index0 = 0 To numbers.GetUpperBound(0)
For index1 = 0 To numbers.GetUpperBound(1)
Console.Write($"{numbers(index0, index1)} ")
Next
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' Output
' 1 2
' 3 4
' 5 6
次の例では 、For Each を使用しています...次のステートメントは、1 次元配列と 2 次元配列を反復処理します。
Module IterateWithForEach
Public Sub Main()
' Declare and iterate through a one-dimensional array.
Dim numbers1 = {10, 20, 30}
For Each number In numbers1
Console.WriteLine(number)
Next
Console.WriteLine()
Dim numbers = {{1, 2}, {3, 4}, {5, 6}}
For Each number In numbers
Console.WriteLine(number)
Next
End Sub
End Module
' The example displays the following output:
' 10
' 20
' 30
'
' 1
' 2
' 3
' 4
' 5
' 6
配列サイズ
配列のサイズは、すべての次元の長さの積です。 配列に現在含まれている要素の合計数を表します。 たとえば、次の例では、各次元に 4 つの要素を含む 2 次元配列を宣言しています。 例からの出力が示すように、配列のサイズは 16 (または (3 + 1) * (3 + 1) です。
Module Example
Public Sub Main()
Dim arr(3, 3) As Integer
Console.WriteLine(arr.Length)
End Sub
End Module
' The example displays the following output:
' 16
注
配列サイズのこの説明は、ジャグ配列には適用されません。 ジャグ配列とジャグ配列のサイズの決定については、「 ジャグ 配列」セクションを参照してください。
配列のサイズは、 Array.Length プロパティを使用して確認できます。 Array.GetLength メソッドを使用すると、多次元配列の各次元の長さを確認できます。
配列変数のサイズを変更するには、新しい配列オブジェクトを割り当てるか、 ReDim
ステートメントを使用します。 次の例では、 ReDim
ステートメントを使用して、100 要素配列を 51 要素配列に変更します。
Module Example
Public Sub Main()
Dim arr(99) As Integer
Console.WriteLine(arr.Length)
Redim arr(50)
Console.WriteLine(arr.Length)
End Sub
End Module
' The example displays the following output:
' 100
' 51
配列のサイズを処理するときは、いくつかの点に留意する必要があります。
注記 | |
---|---|
ディメンションの長さ | 各ディメンションのインデックスは 0 から始まります。つまり、0 から上限までの範囲です。 したがって、指定されたディメンションの長さは、そのディメンションの宣言された上限より 1 大きくなります。 |
長さの制限 | 配列のすべての次元の長さは、 Integer データ型の最大値 ( Int32.MaxValue または (2 ^ 31) - 1) に制限されます。 ただし、配列の合計サイズは、システムで使用可能なメモリによっても制限されます。 使用可能なメモリの量を超える配列を初期化しようとすると、ランタイムは OutOfMemoryExceptionをスローします。 |
サイズと要素のサイズ | 配列のサイズは、その要素のデータ型に依存しません。 サイズは、メモリ内で消費されるバイト数ではなく、要素の合計数を常に表します。 |
メモリ消費量 | 配列がメモリに格納される方法に関する前提を立てることは安全ではありません。 ストレージは異なるデータ幅のプラットフォームによって異なるため、同じ配列は 32 ビット システムよりも 64 ビット システムでより多くのメモリを消費できます。 配列を初期化する際のシステム構成に応じて、共通言語ランタイム (CLR) は、可能な限り近い位置に要素をパックするか、自然なハードウェア境界上でそれらをすべて揃えるために、ストレージを割り当てることができます。 また、配列にはコントロール情報のストレージ オーバーヘッドが必要であり、追加されたディメンションごとにこのオーバーヘッドが増加します。 |
配列型
すべての配列にはデータ型があり、要素のデータ型とは異なります。 すべての配列に 1 つのデータ型はありません。 代わりに、配列のデータ型は、配列の次元数 ( ランク) と配列内の要素のデータ型によって決まります。 2 つの配列変数は、同じランクを持ち、要素のデータ型が同じ場合にのみ、同じデータ型になります。 配列の次元の長さは、配列データ型には影響しません。
すべての配列は System.Array クラスから継承され、変数を Array
型として宣言できますが、 Array
型の配列を作成することはできません。 たとえば、次のコードでは、 arr
変数を Array
型として宣言し、 Array.CreateInstance メソッドを呼び出して配列をインスタンス化しますが、配列の型は Object[] であることが証明されます。
Module Example
Public Sub Main()
Dim arr As Array = Array.CreateInstance(GetType(Object), 19)
Console.WriteLine(arr.Length)
Console.WriteLine(arr.GetType().Name)
End Sub
End Module
' The example displays the following output:
' 19
' Object[]
また、 ReDim ステートメント は、型 Array
として宣言された変数を操作できません。 このような理由から、および型セーフのため、すべての配列を特定の型として宣言することをお勧めします。
配列またはその要素のデータ型は、いくつかの方法で確認できます。
- 変数の GetType メソッドを呼び出して、変数の実行時の型を表す Type オブジェクトを取得できます。 Type オブジェクトは、そのプロパティとメソッドに関する広範な情報を保持します。
-
TypeName関数に変数を渡すと、実行時の型の名前を持つ
String
を取得できます。
次の例では、 GetType
メソッドと TypeName
関数の両方を呼び出して、配列の型を決定します。 配列型は Byte(,)
。
Type.BaseType プロパティは、バイト配列の基本型がArray クラスであることを示すことにも注意してください。
Module Example
Public Sub Main()
Dim bytes(9,9) As Byte
Console.WriteLine($"Type of {nameof(bytes)} array: {bytes.GetType().Name}")
Console.WriteLine($"Base class of {nameof(bytes)}: {bytes.GetType().BaseType.Name}")
Console.WriteLine()
Console.WriteLine($"Type of {nameof(bytes)} array: {TypeName(bytes)}")
End Sub
End Module
' The example displays the following output:
' Type of bytes array: Byte[,]
' Base class of bytes: Array
'
' Type of bytes array: Byte(,)
戻り値とパラメーターとしての配列
Function
プロシージャから配列を返すには、Function ステートメントの戻り値の型として配列データ型と次元数を指定します。 関数内で、同じデータ型と次元数を持つローカル配列変数を宣言します。
Return ステートメントに、かっこのないローカル配列変数を含めます。
Sub
またはFunction
プロシージャのパラメーターとして配列を指定するには、指定したデータ型と次元数を持つ配列としてパラメーターを定義します。 プロシージャの呼び出しで、同じデータ型と次元数を持つ配列変数を渡します。
次の例では、GetNumbers
関数は、Integer
型の 1 次元配列であるInteger()
を返します。
ShowNumbers
プロシージャは、Integer()
引数を受け取ります。
Module ReturnValuesAndParams
Public Sub Main()
Dim numbers As Integer() = GetNumbers()
ShowNumbers(numbers)
End Sub
Private Function GetNumbers() As Integer()
Dim numbers As Integer() = {10, 20, 30}
Return numbers
End Function
Private Sub ShowNumbers(numbers As Integer())
For index = 0 To numbers.GetUpperBound(0)
Console.WriteLine($"{numbers(index)} ")
Next
End Sub
End Module
' The example displays the following output:
' 10
' 20
' 30
次の例では、GetNumbersMultiDim
関数は、Integer
型の 2 次元配列であるInteger(,)
を返します。
ShowNumbersMultiDim
プロシージャは、Integer(,)
引数を受け取ります。
Module Example
Public Sub Main()
Dim numbers As Integer(,) = GetNumbersMultidim()
ShowNumbersMultidim(numbers)
End Sub
Private Function GetNumbersMultidim() As Integer(,)
Dim numbers As Integer(,) = {{1, 2}, {3, 4}, {5, 6}}
Return numbers
End Function
Private Sub ShowNumbersMultidim(numbers As Integer(,))
For index0 = 0 To numbers.GetUpperBound(0)
For index1 = 0 To numbers.GetUpperBound(1)
Console.Write($"{numbers(index0, index1)} ")
Next
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' 1 2
' 3 4
' 5 6
ジャグ配列
アプリケーションのデータ構造が 2 次元で四角形ではない場合があります。 たとえば、配列を使用して、月の各日の高温に関するデータを格納できます。 配列の最初の次元は月を表しますが、2 番目の次元は日数を表し、月の日数は一様ではありません。 ジャグ配列は、配列の配列とも呼ばれ、このようなシナリオ向けに設計されています。 ジャグ配列は、要素も配列である配列です。 ジャグ配列とジャグ配列内の各要素は、1 つ以上の次元を持つことができます。
次の例では、月の配列を使用します。各要素は日の配列です。 この例では、月によって日数が異なるため、ジャグ配列を使用しています。 この例では、ジャグ配列を作成し、それに値を割り当て、その値を取得して表示する方法を示します。
Imports System.Globalization
Module JaggedArray
Public Sub Main()
' Declare the jagged array of 12 elements. Each element is an array of Double.
Dim sales(11)() As Double
' Set each element of the sales array to a Double array of the appropriate size.
For month As Integer = 0 To 11
' The number of days in the month determines the appropriate size.
Dim daysInMonth As Integer =
DateTime.DaysInMonth(Year(Now), month + 1)
sales(month) = New Double(daysInMonth - 1) {}
Next
' Store values in each element.
For month As Integer = 0 To 11
For dayOfMonth = 0 To sales(month).GetUpperBound(0)
sales(month)(dayOfMonth) = (month * 100) + dayOfMonth
Next
Next
' Retrieve and display the array values.
Dim monthNames = DateTimeFormatInfo.CurrentInfo.AbbreviatedMonthNames
' Display the month names.
Console.Write(" ")
For ctr = 0 To sales.GetUpperBound(0)
Console.Write($" {monthNames(ctr)} ")
Next
Console.WriteLine()
' Display data for each day in each month.
For dayInMonth = 0 To 30
Console.Write($"{dayInMonth + 1,2}. ")
For monthNumber = 0 To sales.GetUpperBound(0)
If dayInMonth > sales(monthNumber).GetUpperBound(0) Then
Console.Write(" ")
Else
Console.Write($"{sales(monthNumber)(dayInMonth),-5} ")
End If
Next
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
' 1. 0 100 200 300 400 500 600 700 800 900 1000 1100
' 2. 1 101 201 301 401 501 601 701 801 901 1001 1101
' 3. 2 102 202 302 402 502 602 702 802 902 1002 1102
' 4. 3 103 203 303 403 503 603 703 803 903 1003 1103
' 5. 4 104 204 304 404 504 604 704 804 904 1004 1104
' 6. 5 105 205 305 405 505 605 705 805 905 1005 1105
' 7. 6 106 206 306 406 506 606 706 806 906 1006 1106
' 8. 7 107 207 307 407 507 607 707 807 907 1007 1107
' 9. 8 108 208 308 408 508 608 708 808 908 1008 1108
' 10. 9 109 209 309 409 509 609 709 809 909 1009 1109
' 11. 10 110 210 310 410 510 610 710 810 910 1010 1110
' 12. 11 111 211 311 411 511 611 711 811 911 1011 1111
' 13. 12 112 212 312 412 512 612 712 812 912 1012 1112
' 14. 13 113 213 313 413 513 613 713 813 913 1013 1113
' 15. 14 114 214 314 414 514 614 714 814 914 1014 1114
' 16. 15 115 215 315 415 515 615 715 815 915 1015 1115
' 17. 16 116 216 316 416 516 616 716 816 916 1016 1116
' 18. 17 117 217 317 417 517 617 717 817 917 1017 1117
' 19. 18 118 218 318 418 518 618 718 818 918 1018 1118
' 20. 19 119 219 319 419 519 619 719 819 919 1019 1119
' 21. 20 120 220 320 420 520 620 720 820 920 1020 1120
' 22. 21 121 221 321 421 521 621 721 821 921 1021 1121
' 23. 22 122 222 322 422 522 622 722 822 922 1022 1122
' 24. 23 123 223 323 423 523 623 723 823 923 1023 1123
' 25. 24 124 224 324 424 524 624 724 824 924 1024 1124
' 26. 25 125 225 325 425 525 625 725 825 925 1025 1125
' 27. 26 126 226 326 426 526 626 726 826 926 1026 1126
' 28. 27 127 227 327 427 527 627 727 827 927 1027 1127
' 29. 28 228 328 428 528 628 728 828 928 1028 1128
' 30. 29 229 329 429 529 629 729 829 929 1029 1129
' 31. 30 230 430 630 730 930 1130
前の例では、 For...Next
ループを使用して、要素ごとにジャグ配列に値を割り当てます。 入れ子になった配列リテラルを使用して、ジャグ配列の要素に値を割り当てることもできます。 ただし、入れ子になった配列リテラル (たとえば、 Dim valuesjagged = {{1, 2}, {2, 3, 4}}
) を使用しようとすると、コンパイラ エラー BC30568が生成されます。 エラーを修正するには、内部配列リテラルをかっこで囲みます。 次の例に示すように、かっこによって配列リテラル式が強制的に評価され、結果の値が外側の配列リテラルと共に使用されます。
Module Example
Public Sub Main()
Dim values1d = { 1, 2, 3 }
Dim values2d = {{1, 2}, {2, 3}, {3, 4}}
Dim valuesjagged = {({1, 2}), ({2, 3, 4})}
End Sub
End Module
ジャグ配列は、要素に配列が含まれる 1 次元配列です。 したがって、 Array.Length プロパティと Array.GetLength(0)
メソッドは、1 次元配列内の要素の数を返し、ジャグ配列が多次元ではないため、 Array.GetLength(1)
は IndexOutOfRangeException をスローします。 各サブ配列の Array.Length プロパティの値を取得して、各サブ配列内の要素の数を決定します。 次の例は、ジャグ配列内の要素の数を決定する方法を示しています。
Module Example
Public Sub Main()
Dim jagged = { ({1, 2}), ({2, 3, 4}), ({5, 6}), ({7, 8, 9, 10}) }
Console.WriteLine($"The value of jagged.Length: {jagged.Length}.")
Dim total = jagged.Length
For ctr As Integer = 0 To jagged.GetUpperBound(0)
Console.WriteLine($"Element {ctr + 1} has {jagged(ctr).Length} elements.")
total += jagged(ctr).Length
Next
Console.WriteLine($"The total number of elements in the jagged array: {total}")
End Sub
End Module
' The example displays the following output:
' The value of jagged.Length: 4.
' Element 1 has 2 elements.
' Element 2 has 3 elements.
' Element 3 has 2 elements.
' Element 4 has 4 elements.
' The total number of elements in the jagged array: 15
長さ 0 の配列
Visual Basic では、初期化されていない配列 (値が Nothing
の配列) と 長さ 0 の配列 または空の配列 (要素のない配列) を区別します。初期化されていない配列は、次元化されていない配列、または値が割り当てられていない配列です。 例えば次が挙げられます。
Dim arr() As String
長さ 0 の配列は、次元 -1 で宣言されます。 例えば次が挙げられます。
Dim arrZ(-1) As String
次の状況では、長さ 0 の配列を作成することが必要になる場合があります。
NullReferenceException例外を危険にさらすことなく、コードはLengthやRankなどのArray クラスのメンバーにアクセスするか、UBoundなどの Visual Basic 関数を呼び出す必要があります。
特別なケースとして
Nothing
を確認する必要がないようにして、コードをシンプルに保つ必要があります。コードは、長さ 0 の配列を 1 つ以上のプロシージャに渡す必要があるアプリケーション プログラミング インターフェイス (API) と対話するか、1 つ以上のプロシージャから長さ 0 の配列を返します。
配列の分割
場合によっては、1 つの配列を複数の配列に分割する必要があります。 これには、配列を分割するポイントを識別し、配列を 2 つ以上の個別の配列にスパッティングする必要があります。
注
このセクションでは、区切り記号に基づいて 1 つの文字列を文字列配列に分割する方法については説明しません。 文字列を分割する方法については、 String.Split メソッドを参照してください。
配列を分割するための最も一般的な条件は次のとおりです。
配列内の 要素の数。 たとえば、指定した数を超える要素の配列を、ほぼ等しい数に分割できます。 このため、 Array.Length メソッドまたは Array.GetLength メソッドによって返される値を使用できます。
配列を分割する場所を示す区切り記号として機能する要素の値。 Array.FindIndexメソッドとArray.FindLastIndexメソッドを呼び出すことで、特定の値を検索できます。
配列を分割するインデックスまたはインデックスを決定したら、 Array.Copy メソッドを呼び出して個々の配列を作成できます。
次の例では、配列をほぼ等しいサイズの 2 つの配列に分割します。 (配列要素の合計数が奇数の場合、最初の配列には 2 番目の要素より 1 つ多い要素があります)。
Module Example
Public Sub Main()
' Create an array of 100 elements.
Dim arr(99) As Integer
' Populate the array.
Dim rnd As new Random()
For ctr = 0 To arr.GetUpperBound(0)
arr(ctr) = rnd.Next()
Next
' Determine how many elements should be in each array.
Dim divisor = 2
Dim remainder As Integer
Dim boundary = Math.DivRem(arr.GetLength(0), divisor, remainder)
' Copy the array.
Dim arr1(boundary - 1 + remainder), arr2(boundary - 1) as Integer
Array.Copy(arr, 0, arr1, 0, boundary + remainder)
Array.Copy(arr, boundary + remainder, arr2, 0, arr.Length - boundary)
End Sub
End Module
次の例では、配列区切り記号として機能する値が "zzz" である要素の存在に基づいて、文字列配列を 2 つの配列に分割します。 新しい配列には、区切り記号を含む要素は含まれません。
Module Example
Public Sub Main()
Dim rnd As New Random()
' Create an array of 100 elements.
Dim arr(99) As String
' Populate each element with an arbitrary ASCII character.
For ctr = 0 To arr.GetUpperBound(0)
arr(ctr) = ChrW(Rnd.Next(&h21, &h7F))
Next
' Get a random number that will represent the point to insert the delimiter.
arr(rnd.Next(0, arr.GetUpperBound(0))) = "zzz"
' Find the delimiter.
Dim ___location = Array.FindIndex(arr, Function(x) x = "zzz")
' Create the arrays.
Dim arr1(___location - 1) As String
Dim arr2(arr.GetUpperBound(0) - ___location - 1) As String
' Populate the two arrays.
Array.Copy(arr, 0, arr1, 0, ___location)
Array.Copy(arr, ___location + 1, arr2, 0, arr.GetUpperBound(0) - ___location)
End Sub
End Module
配列を結合する
複数の配列を 1 つの大きな配列に結合することもできます。 これを行うには、 Array.Copy メソッドも使用します。
注
このセクションでは、文字列配列を 1 つの文字列に結合する方法については説明しません。 文字列配列を結合する方法については、 String.Join メソッドを参照してください。
各配列の要素を新しい配列にコピーする前に、まず、新しい配列を格納するのに十分な大きさになるように配列を初期化しておく必要があります。 これは、次の 2 つの方法のいずれかで行うことができます。
- 新しい要素を追加する前に、
ReDim Preserve
ステートメントを使用して配列を動的に展開します。 これは最も簡単な手法ですが、大きな配列をコピーするときにパフォーマンスの低下や過剰なメモリ消費が発生する可能性があります。 - 新しい大きな配列に必要な要素の合計数を計算し、各ソース配列の要素をそれに追加します。
次の例では、2 番目の方法を使用して、それぞれ 10 個の要素を持つ 4 つの配列を 1 つの配列に追加します。
Imports System.Collections.Generic
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim tasks As New List(Of Task(Of Integer()))
' Generate four arrays.
For ctr = 0 To 3
Dim value = ctr
tasks.Add(Task.Run(Function()
Dim arr(9) As Integer
For ndx = 0 To arr.GetUpperBound(0)
arr(ndx) = value
Next
Return arr
End Function))
Next
Task.WaitAll(tasks.ToArray())
' Compute the number of elements in all arrays.
Dim elements = 0
For Each task In tasks
elements += task.Result.Length
Next
Dim newArray(elements - 1) As Integer
Dim index = 0
For Each task In tasks
Dim n = task.Result.Length
Array.Copy(task.Result, 0, newArray, index, n)
index += n
Next
Console.WriteLine($"The new array has {newArray.Length} elements.")
End Sub
End Module
' The example displays the following output:
' The new array has 40 elements.
この場合、ソース配列はすべて小さいため、新しい各配列の要素を追加する際に、配列を動的に展開することもできます。 次の例では、この処理を行います。
Imports System.Collections.Generic
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim tasks As New List(Of Task(Of Integer()))
' Generate four arrays.
For ctr = 0 To 3
Dim value = ctr
tasks.Add(Task.Run(Function()
Dim arr(9) As Integer
For ndx = 0 To arr.GetUpperBound(0)
arr(ndx) = value
Next
Return arr
End Function))
Next
Task.WaitAll(tasks.ToArray())
' Dimension the target array and copy each element of each source array to it.
Dim newArray() As Integer = {}
' Define the next position to copy to in newArray.
Dim index = 0
For Each task In tasks
Dim n = Task.Result.Length
ReDim Preserve newArray(newArray.GetUpperBound(0) + n)
Array.Copy(task.Result, 0, newArray, index, n)
index += n
Next
Console.WriteLine($"The new array has {newArray.Length} elements.")
End Sub
End Module
' The example displays the following output:
' The new array has 40 elements.
配列に代わるコレクション
配列は、厳密に型指定されたオブジェクトの固定数を作成して操作する場合に最も便利です。 コレクションは、オブジェクトのグループを操作するためのより柔軟な方法を提供します。
ReDim
ステートメントを使用して配列のサイズを明示的に変更する必要がある配列とは異なり、コレクションはアプリケーションのニーズの変化に応じて動的に拡大および縮小されます。
ReDim
を使用して配列を再入力すると、Visual Basic によって新しい配列が作成され、前の配列が解放されます。 これには実行時間がかかります。 そのため、頻繁に変更を処理している項目の数や、必要な項目の最大数を予測できない場合は、通常、コレクションを使用してパフォーマンスが向上します。
一部のコレクションでは、コレクションに配置した任意のオブジェクトにキーを割り当てて、キーを使用してオブジェクトをすばやく取得できるようにすることができます。
コレクションに 1 つのデータ型のみの要素が含まれている場合は、 System.Collections.Generic 名前空間のいずれかのクラスを使用できます。 ジェネリック コレクションでは、他のデータ型を追加できないように、型セーフが適用されます。
コレクションの詳細については、「 コレクション」を参照してください。
関連トピック
任期 | 定義 |
---|---|
Visual Basic の配列ディメンション | 配列内のランクと次元について説明します。 |
方法: Visual Basic で配列変数を初期化する | 配列に初期値を設定する方法について説明します。 |
方法: Visual Basic で配列を並べ替える | 配列の要素をアルファベット順に並べ替える方法を示します。 |
方法: ある配列を別の配列に割り当てる | 配列を別の配列変数に割り当てる規則と手順について説明します。 |
配列のトラブルシューティング | 配列を操作するときに発生するいくつかの一般的な問題について説明します。 |
こちらも参照ください
.NET