次の方法で共有


Visual Basic における配列

配列は、学校の各学年の生徒の数など、互いに論理的に関連する一連の値です。

配列を使うと、これらの関連する値を同じ名前で参照できます。配列の各要素を区別するには、インデックスまたは添字と呼ばれる番号を使います。 個々の値は、配列の要素と呼ばれます。 これは、インデックス 0 から最も大きいインデックス値まで連続しています。

配列とは対照的に、変数には、スカラー変数と呼ばれる単一の値が含まれています。

次の例では、学校の各学年の生徒の数を保持するために、配列変数を宣言しています。

Dim students(6) As Integer

上の例の students 配列には、7 つの要素が含まれています。 要素のインデックスの範囲は 0 から 6 までです。 7 つの異なる変数を宣言するよりも、この配列の方がより簡単です。

students 配列を次の図に示します。 配列の各要素は、次のとおりです。

  • 要素のインデックスは、学年を表します (インデックス 0 は幼稚園を表します)。

  • 要素に含まれている値は、その学年の生徒の数を表します。

"生徒" 配列の要素

生徒数を示す配列の図

次の例は、students 配列の先頭の要素、2 番目の要素、および最後の要素を参照する方法を示します。

Dim kindergarten As Integer = students(0)
Dim firstGrade As Integer = students(1)
Dim sixthGrade As Integer = students(6)
MsgBox("Students in kindergarten = " & CStr(kindergarten))
MsgBox("Students in first grade = " & CStr(firstGrade))
MsgBox("Students in sixth grade = " & CStr(sixthGrade))

インデックスを持たない配列変数名だけを使用して、配列全体を参照できます。

配列の次元

前の例の students 配列では、1 つのインデックスが使用されており、これを 1 次元と言います。 複数のインデックスまたは添字が使用されている配列は、多次元と呼ばれます。 詳細については、「Visual Basic における配列の次元」を参照してください。

他の種類の配列とは、要素として他の配列を保持している配列です。 これは、配列の配列またはジャグ配列と呼ばれます。 ジャグ配列およびその要素は、1 次元または多次元のいずれかになることができます。 アプリケーションのデータ構造は、2 次元の配列であっても四角形の 2 次元配列ではない場合があります。 たとえば、月の配列があり、その各要素が日の配列である場合があります。 月によって日数が異なるため、月要素は四角形の 2 次元配列を形成しません。 このような場合に、多次元配列の代わりにジャグ配列を使用できます。

配列の宣言

配列変数は、他の変数と同じように Dim ステートメントを使用して宣言します。 変数名に続けて 1 組以上のかっこを記述することにより、その変数がスカラー (1 つの値を含む変数) ではなく配列を保持することを示します。

1 次元配列変数を宣言するには、変数名の後に 1 組のかっこを追加します。

Dim cargoWeights() As Double

多次元配列変数を宣言するには、変数名の後に 1 組のかっこを追加し、かっこの中にコンマを記入して次元を区切ります。

Dim atmospherePressures(,,,) As Short

ジャグ配列変数を宣言するには、入れ子になった配列 1 レベルにつき 1 組のかっこを変数名の後に追加します。

Dim inquiriesByYearMonthDay()()() As Byte

上の例では、配列変数を宣言しますが、配列は割り当てられません。 配列を作成して初期化し、変数に割り当てる必要があります。

長さ 0 の配列

要素を持たない配列は、長さ 0 の配列と呼ばれます。 長さ 0 の配列を保持する変数には、Nothing 値が保持されているのではありません。 要素を持たない配列を作成するには、次の例のように配列の次元のいずれかを -1 に宣言します。

Dim twoDimensionalStrings(-1, 3) As String

次のような場合に、長さ 0 の配列を作成する必要があります。

  • コードで、LengthRank などの Array クラスのメンバーにアクセスする必要がある場合、または NullReferenceException 例外を発生させることなく、UBound などの Visual Basic 関数を呼び出す必要がある場合。

  • 特別なケースですが、Nothing をチェックする必要性をなくすことによって利用側のコードを簡素化する場合。

  • コードで、長さ 0 の配列を 1 つ以上のプロシージャに渡す必要があるアプリケーション プログラミング インターフェイス (API: Application Programming Interface) とやり取りする場合、または API の 1 つ以上のプロシージャから長さ 0 の配列が返される場合。

配列の作成

配列を作成する方法は 2 つあります。 配列を宣言するときにサイズを指定する方法と、配列はオブジェクトであることを利用して、New 演算子 (Visual Basic) 句を使用して配列を作成してから配列変数に割り当てる方法です。 この操作は、配列宣言の一部として行うことも、次の例に示すように後続の代入ステートメントで行うこともできます。

cargoWeights = New Double() {}
atmospherePressures = New Short(,,,) {}
inquiriesByYearMonthDay = New Byte()()() {}

これらのステートメントを実行すると、配列の長さが 0 になります。

注意

New 句では、型名に続けてかっこを指定し、かっこに続けて中かっこ ({}) を指定する必要があります。 かっこは、配列コンストラクターへの呼び出しを表しているわけではありません。 かっこは、オブジェクト型が配列型であることを示しています。 中かっこには初期値を指定できます。 値を指定しない場合でも、コンパイラは中かっこを要求します。 したがって、New 句には、どちらにも値がない場合でも、かっこと中かっこの両方を含める必要があります。 中かっこを含めないと、コンパイラでは、指定された型のコンストラクターを呼び出していると見なします。

配列のサイズは、さまざまな方法で定義できます。 次の例に示すように、配列を宣言するときにサイズを指定することができます。

Dim cargoWeights(10) As Double
Dim atmospherePressures(2, 2, 4, 10) As Short
Dim inquiriesByYearMonthDay(20)()() As Byte

また、次の例に示すように、New 句を使用して配列を作成するときにサイズを指定することもできます。

cargoWeights = New Double(10) {}
atmospherePressures = New Short(2, 2, 4, 10) {}
inquiriesByYearMonthDay = New Byte(20)()() {}

既存の配列がある場合は、Redim ステートメントを使用してサイズを再定義できます。 Redim ステートメントでは、配列に現在格納されている値を保持するように指定することも、新しい空の配列を作成するように指定することもできます。 次に、Redim ステートメントを使用して既存の配列のサイズを変更する例をいくつか示します。

' Assign a new array size and retain the current element values.
ReDim Preserve cargoWeights(20)
' Assign a new array size and retain only the first five element values.
ReDim Preserve cargoWeights(4)
' Assign a new array size and discard all current element values.
ReDim cargoWeights(15)

詳細については、「ReDim ステートメント (Visual Basic)」を参照してください。

配列への初期値の取り込み

配列リテラルを使用すると、初期値のセットを含む配列を作成できます。 配列リテラルは、中かっこ ({}) で囲んだ値のコンマ区切りの一覧で構成されます。

配列リテラルを使用して配列を作成する場合、配列の型を指定するか、型の推論を使用して配列の型を決定することができます。 両方の例を次のコードに示します。

Dim numbers = New Integer() {1, 2, 4, 8}
Dim doubles = {1.5, 2, 9.9, 18}

型の推論を使用する場合、配列の型は、配列リテラルに指定された値の一覧の中で最も優先度の高い型によって決まります。 最も優先度の高い型は、配列リテラル内の他のすべての型に拡大変換できる一意の型です。 この一意の型を特定できない場合、最も優先度の高い型は、配列内の他のすべての型に縮小変換できる一意の型になります。 これらの一意の型をどちらも特定できない場合は、Object が最も優先度の高い型になります。 たとえば、配列リテラルに指定された値の一覧に Integer 型、Long 型、および Double 型の値が含まれている場合、結果の配列の型は Double です。 Integer と Long はどちらも Double に拡大変換され、Double だけになります。 そのため、Double が最も優先度の高い型になります。 詳細については、「拡大変換と縮小変換 (Visual Basic)」を参照してください。 これらの推論規則は、クラス メンバーで定義されたローカル変数である配列についての型の推論に適用されます。 クラス レベルの変数を作成するときに配列リテラルを使用することはできますが、クラス レベルで型の推論を使用することはできません。 そのため、クラス レベルで指定された配列リテラルでは、配列リテラルに指定された値の型は Object 型であると推論されます。

配列リテラルを使用して作成した配列の要素の型を明示的に指定することができます。 この場合、配列リテラル内の値を配列の要素の型に拡大変換する必要があります。 整数の一覧から Double 型の配列を作成するコード例を次に示します。

Dim values As Double() = {1, 2, 3, 4, 5, 6}

入れ子になった配列リテラル

入れ子になった配列リテラルを使用すると、多次元配列を作成できます。 入れ子になった配列リテラルに含める次元および次元数 (ランク) は、結果の配列と一致する必要があります。 配列リテラルを使用して整数の 2 次元配列を作成するコード例を次に示します。

Dim grid = {{1, 2}, {3, 4}}

上記の例では、入れ子になった配列リテラル内の要素の数が一致しないとエラーが発生します。 また、2 次元以外の配列変数が明示的に宣言された場合もエラーが発生します。

注意

入れ子になった配列リテラルで異なる次元を指定する場合のエラーを回避するには、内側の配列をかっこで囲みます。 かっこで囲むことで、配列リテラル式が強制的に評価され、外側の配列リテラルで結果の値が使用されるようになります。 コードは次のようになります。

Dim values = {({1, 2}), ({3, 4, 5})}

入れ子になった配列リテラルを使用して多次元配列を作成する場合、型の推論を使用できます。 型の推論を使用すると、推論される型は、入れ子レベルのすべての配列リテラルに含まれるすべての値の中で最も優先度の高い型になります。 Integer 型と Double 型の値から Double 型の 2 次元配列を作成するコード例を次に示します。

Dim a = {{1, 2.0}, {3, 4}, {5, 6}, {7, 8}}

その他の例については、「方法: Visual Basic で配列変数を初期化する」を参照してください。

配列への値の格納

配列のそれぞれの位置には、Integer 型のインデックスを使用してアクセスできます。 かっこで囲まれたインデックスを使用して配列のそれぞれの位置を参照することで、配列の値を格納および取得することができます。 多次元配列のインデックスはコンマ (,) で区切ります。配列の次元ごとに 1 つのインデックスが必要です。 配列に値を格納するステートメントの例を示します。

Dim i = 4
Dim j = 2

Dim numbers(10) As Integer
Dim matrix(5, 5) As Double

numbers(i + 1) = 0
matrix(3, j * 2) = j

配列から値を取得するステートメントの例を示します。

Dim v = 2
Dim i = 1
Dim j = 1
Dim k = 1
Dim wTotal As Double = 0.0
Dim sortedValues(5), rawValues(5), estimates(2, 2, 2) As Double
Dim lowestValue = sortedValues(0)
wTotal += (rawValues(v) ^ 2)
Dim firstGuess = estimates(i, j, k)

配列の次元ごとに、GetUpperBound メソッドではインデックスが保持できる一番高い値が返されます。 一番低いインデックス値は常に 0 です。

配列のサイズ

配列のサイズは、そのすべての次元の長さの積です。 これは、現在配列に含まれている要素の総数を表します。

次の例では 3 次元配列を宣言しています。

Dim prices(3, 4, 5) As Long

変数 prices の配列の全体のサイズは、(3 + 1) x (4 + 1) x (5 + 1) = 120 です。

配列のサイズは、Length プロパティを使用して確認できます。 多次元配列の各次元の長さは、GetLength メソッドを使用して確認できます。

配列変数のサイズを変更するには、新しい配列オブジェクトを割り当てるか、ReDim ステートメントを使用します。

配列のサイズを扱う際に考慮する必要があるいくつかの点があります。

次元の長さ

各次元のインデックスは 0 ベースであり、範囲は 0 から上限です。 したがって、次元の長さは、その次元に対する宣言された上限よりも 1 だけ大きくなります。

長さの制限

配列のすべての次元の長さは、(2 ^ 31) - 1 である Integer データ型の最大値に制限されます。 しかし、配列のサイズの総数も、システムで利用できるメモリによって制限されます。 利用できる RAM の容量を超える配列を初期化する場合、共通言語ランタイムは OutOfMemoryException 例外をスローします。

サイズおよび要素のサイズ

配列のサイズは、その要素のデータ型には依存しません。 サイズは常に、使用するストレージのバイト数ではなく、要素の合計数を表します。

メモリの使用量

配列がメモリに格納される方法に関して、推測で行うのは安全ではありません。 ストレージは、データ幅の異なるプラットフォームによって変わります。したがって、配列が同じであれば、32 ビットのシステムよりも、64 ビットのシステムのほうがより多くのメモリを使用します。 配列を初期化するとき、システム構成に応じて、要素をできるだけ近くに集めるように、またはハードウェア本来の境界条件にすべてをそろえるように、共通言語ランタイム (CLR: Common Language Runtime) によってストレージが割り当てられます。 また、配列は制御情報のためのストレージのオーバーヘッドを必要とします。このオーバーヘッドは、次元が追加されるごとに増加します。

配列の型および他の型

データ型

すべての配列にデータ型がありますが、要素のデータ型とは異なります。 すべての配列を包括する 1 つのデータ型はありません。 代わりに、配列のデータ型は、配列の次元数 (ランク) と配列の要素のデータ型によって決まります。 ランクと要素のデータ型が一致しない限り、2 つの配列変数が同じデータ型を持つと見なされることはありません。 配列の各次元の長さは、配列のデータ型には影響しません。

すべての配列は、System.Array クラスから継承しています。また、Array 型として変数を宣言できますが、Array 型の配列は作成できません。 また、ReDim ステートメント (Visual Basic) は、Array 型として宣言された変数上では使用できません。 これらの理由やタイプ セーフにより、すべての配列を、前の例の Integer などの特定の型として宣言することをお勧めします。

いくつかの方法で、配列またはその要素のいずれかのデータ型を知ることができます。

  • 変数の Object.GetType メソッドを呼び出して、実行時型の変数の Type オブジェクトを取得できます。 Type オブジェクトでは、プロパティおよびメソッドに詳細情報が保持されます。

  • 変数を TypeName 関数に渡して、実行時型の名前が含まれる String を取得できます。

  • 変数を VarType 関数に渡して、変数の型の分類を表す VariantType値を受け取ることができます。

TypeName 関数を呼び出して配列の型と配列の要素の型を確認する例を次に示します。 配列の型は Integer(,) で、配列の要素の型は Integer です。

Dim thisTwoDimArray(,) As Integer = New Integer(9, 9) {}
MsgBox("Type of thisTwoDimArray is " & TypeName(thisTwoDimArray))
MsgBox("Type of thisTwoDimArray(0, 0) is " & TypeName(thisTwoDimArray(0, 0)))

配列の代わりとしてのコレクション

コレクションは、通常は オブジェクト型 (Object) の操作に使われますが、任意のデータ型の操作にも使用できます。 配列よりもコレクションにアイテムを格納した方が効率的な場合もあります。

配列のサイズを変更する必要がある場合、ReDim ステートメント (Visual Basic) を使用する必要があります。 これを行うと、Visual Basic により新しい配列が作成され、前の配列が解放されて廃棄されます。 これには、実行時間がかかります。 したがって、操作を行う項目の数が頻繁に変更される場合、または必要な項目の最大数を予測できない場合、コレクションを使用するとパフォーマンスが向上します。

コレクションは、新しいオブジェクトを作成したり、既存の要素をコピーする必要がないため、ReDim を使用する必要がある配列よりも、短い実行時間でサイズ変更の処理ができます。 サイズが変更されない場合、またはほとんど変更されない場合、配列の方がより効率的です。 通常どおり、パフォーマンスは個々のアプリケーションに大きく依存します。 配列とコレクションの両方を試してみる価値はあります。

専用コレクション

また、.NET Framework には、さまざまなクラス、インターフェイス、および構造体が、一般的および特殊なコレクション用に用意されています。 System.Collections および System.Collections.Specialized 名前空間には、ディクショナリ、一覧、キュー、およびスタックを含む、定義および実装が含まれています。 System.Collections.Generic 名前空間には、1 つ以上の型の引数を指定できる、これらのジェネリック バージョンが数多く用意されています。

コレクションが特定のデータ型だけの要素を保持する場合、ジェネリック コレクションはタイプ セーフを強制するという点で有利です。 ジェネリックの詳細については、「Visual Basic におけるジェネリック型 (Visual Basic)」を参照してください。

専用コレクション

また、.NET Framework には、さまざまなクラス、インターフェイス、および構造体が、一般的および特殊なコレクション用に用意されています。 System.Collections および System.Collections.Specialized 名前空間には、ディクショナリ、一覧、キュー、およびスタックを含む、定義および実装が含まれています。 System.Collections.Generic 名前空間には、1 つ以上の型の引数を指定できる、これらのジェネリック バージョンが数多く用意されています。

コレクションが特定のデータ型だけの要素を保持する場合、ジェネリック コレクションはタイプ セーフを強制するという点で有利です。 ジェネリックの詳細については、「Visual Basic におけるジェネリック型 (Visual Basic)」を参照してください。

.NET Framework のジェネリック クラス System.Collections.Generic.List<T> を使用して、Customer オブジェクトの一覧コレクションを作成する例を次に示します。

' Define the class for a customer.
Public Class Customer
    Public Property Name As String
    ' Insert code for other members of customer structure.
End Class

' Create a module-level collection that can hold 200 elements.
Public CustomerList As New List(Of Customer)(200)

' Add a specified customer to the collection.
Private Sub AddNewCustomer(ByVal newCust As Customer)
    ' Insert code to perform validity check on newCust.
    CustomerList.Add(newCust)
End Sub

' Display the list of customers in the Debug window.
Private Sub PrintCustomers()
    For Each cust As Customer In CustomerList
        Debug.WriteLine(cust)
    Next cust
End Sub

CustomerFile コレクションの宣言により、Customer 型だけの要素を含むことができることを指定します。 また、200 要素分の初期容量も用意されています。 AddNewCustomer プロシージャにより、新しい要素の有効性がチェックされ、コレクションに追加されます。 PrintCustomers プロシージャでは、コレクションを走査し、その要素を表示するために、For Each ループが使用されます。

関連トピック

語句

定義

Visual Basic における配列の次元

配列のランクと次元について説明します。

方法: Visual Basic で配列変数を初期化する

配列に初期値を設定する方法について説明します。

方法: 配列内の内容を反転させる (Visual Basic)

配列の要素を逆順に並べ替える方法について説明します。

方法: 配列を並べ替える (Visual Basic)

配列の要素をアルファベット順に並べ替える方法について説明します。

方法: 配列を別の配列に代入する (Visual Basic)

配列を別の配列変数に代入するときの手順と規則を説明します。

方法: 配列を他の配列に変更する (Visual Basic)

実行可能な変更と変更の手順を説明します。

方法: プロシージャまたはプロパティに配列を渡す (Visual Basic)

配列をプロシージャまたはプロパティに引数として渡す方法を説明します。

方法: プロシージャまたはプロパティから配列を返す (Visual Basic)

プロシージャまたはプロパティを呼び出すコードに配列を返す方法を説明します。

配列のトラブルシューティング (Visual Basic)

配列を使用しているときに発生する一般的な問題について説明します。

参照

参照

Dim ステートメント (Visual Basic)

ReDim ステートメント (Visual Basic)

Array