Visual Basic 中的陣列

陣列是一組稱為元素的值,這些元素在邏輯上彼此相關。 例如,陣列可能包含文法學校中每個年級的學生數目;陣列的每個元素是單一年級的學生數目。 同樣地,陣列可能包含班級的學生年級;陣列的每個元素都是單一年級。

您可以使用個別變數來儲存每個資料項目。 例如,如果我們的應用程式分析學生成績,我們可以針對每個學生的年級使用不同的變數,例如 englishGrade1englishGrade2 等。此方法有三個主要限制:

  • 我們必須在設計階段知道我們必須處理的年級數目。
  • 處理大量年級很快會變得龐大。 如此一來,應用程式便更可能有嚴重的錯誤 (bug)。
  • 難以維護。 我們增加的每個新年級都需要修改、重新編譯和重新部署應用程式。

藉由使用陣列,您可以以相同名稱參照這些相關值,並使用稱為索引下標的數字,以根據其在陣列中的位置來識別個別元素。 陣列的索引範圍從 0 到陣列中元素的總數減一。 使用 Visual Basic 語法來定義陣列的大小時,您可以指定其最高索引,而不是陣列中的元素總數。 您可以使用陣列做為單位,而且能夠逐一查看其元素,讓您不必知道在設計階段包含的元素數目。

開始說明前,先提供一些簡單的範例:

' 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。 使用此陣列較宣告七個不同的變數來得簡單。

下圖顯示 students 陣列。 對於陣列的每一項目︰

  • 項目的索引代表年級 (索引 0 代表幼稚園)。

  • 項目包含的值代表該年級的學生數目。

Diagram showing an array of the numbers of students

下列範例包含會建立和使用陣列的 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

範例會執行三件事:

  • 它會宣告具有七個元素的 students 陣列。 陣列宣告中的數字 6 表示陣列中的最後一個索引;其小於陣列中的元素數目。
  • 它會將值指派給陣列中的每個元素。 陣列元素是使用陣列名稱來存取,並在括弧中包含個別元素的索引。
  • 它會列出陣列的每個值。 範例會使用 For 陳述式,依陣列的索引編號來存取陣列的每個元素。

上述範例中的 students 陣列是一維陣列,因為它使用一個索引。 使用一個以上的索引或註標則稱為多維。 如需詳細資訊,請參閱本文章和 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的索引來存取陣列中的每一個位置。 使用括弧內的陣列索引即可參照各陣列的位置,從而儲存並擷取陣列中的值。 多維陣列的索引以逗號 (,) 分隔。 各個陣列維度皆需一個索引。

下列範例顯示一些將值儲存並擷取在陣列中的陳述式。


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。 例如,如果提供給陣列常值的值清單含有類型值 IntegerLongDouble,則結果陣列的類型是 Double。 因為 IntegerLong 只會擴展為 DoubleDouble 是主控項型別。 如需詳細資訊,請參閱 Widening and Narrowing Conversions

注意

您只能針對在型別成員中定義為區域變數的陣列使用型別推斷。 如果明確型別定義不存在,在類別層級以陣列常值定義的陣列會是型別 Object[]。 如需詳細資訊,請參閱區域型別推斷

請注意,即使所有陣列常值都屬於型別 Integer,上述範例仍會將 values 定義為型別 Double 的陣列。 您可以建立此陣列,因為陣列常值中的值可以擴展為 Double 值。

您也可以使用巢狀陣列常值來建立和填入多維陣列。 巢狀陣列常值必須具有與結果陣列一致的維度數目。 下列範例將使用巢狀陣列常值建立整數的二維陣列。

' 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}}

使用巢狀陣列常值來建立和填入陣列時,如果巢狀陣列常值中的元素數目不符,就會發生錯誤。 如果您明確宣告陣列變數有與陣列常值不同的維度數目,也會發生錯誤。

就像一維陣列一樣,在建立具有巢狀陣列常值的多維度陣列時,您可以依賴型別推斷。 推斷的型別是某個巢狀層次之所有陣列常值中所有值的主型別。 下列範例將從型別為 IntegerDouble 的值建立型別為 Double[,] 的二維陣列。

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

如需其他範例,請參閱如何:在 Visual Basic 中初始化陣列變數

逐一查看陣列

當您逐一查看陣列時,您會從最低的索引到最高的索引或從最高的索引到最低的索引來存取陣列中的每個元素。 一般而言,使用 For...Next 陳述式For Each...Next 陳述式,以逐一查看陣列的元素。 當您不知道陣列的上限時,您可以呼叫 Array.GetUpperBound 方法以取得索引的最高值。 雖然最低索引值幾乎一律為 0,但您可以呼叫 Array.GetLowerBound 方法來取得索引的最低值。

下列範例會使用 For...Next 陳述式逐一查看一維陣列。


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) 會傳回第二個維度的最高索引。


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...Next 陳述式,以逐一查看一維陣列和二維陣列。


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

陣列大小

陣列大小為其所有維度長度之乘積。 它代表目前包含於陣列中的項目總數。 例如,下列範例會宣告每個維度中有四個元素的 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 到它的上限為止。 因此,指定維度的長度會比該維度宣告的上限多一。
長度限制 陣列的每個維度長度都受限於 Integer 資料型別的最大值,也就是 Int32.MaxValue 或 (2 ^ 31) - 1。 然而,陣列之總大小也同時受限於系統可用的記憶體。 若您嘗試初始化超過可用記憶體的陣列,執行階段將擲回 OutOfMemoryException
大小及項目大小 陣列大小與其項目的資料類型無關。 大小一律是指元素的總數,而不是它們於記憶體中所佔的位元組。
記憶體使用量 對陣列在記憶體中的儲存方式做任何假設都是不安全的。 儲存體會因不同資料寬度的平台而有差異,所以相同陣列於 64 位元系統上所佔記憶體將較 32 位元系統來的多。 當您初始化陣列時,隨著系統組態不同,通用語言執行平台 (CLR) 會指派儲存體盡可能將項目存放在一起,或是根據實體硬體界限全部加以調整。 同時,陣列需要耗用儲存體以供其控制資訊使用,此消耗量會隨著維度增加而增加。

陣列型別

每個陣列都具有其資料型別,其與陣列元素的資料型別不同。 沒有任何單一的資料類型適用於所有的陣列。 陣列的類型反而是由陣列的維度數目,或稱為 「順位」(rank) 以及陣列項目的資料類型所決定。 只要兩個陣列變數具有相同的順位且其元素具有相同的資料型別,便具有相同資料型別。 陣列中維度的長度不會影響陣列的資料型別。

每個陣列都繼承自 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(),即型別 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(,),即型別 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

不規則陣列

有時候應用程式中的資料結構會是非矩形的二維陣列。 例如,您可以使用陣列來儲存有關當月每天溫度的資料。 陣列的第一個維度代表月份,但第二個維度代表天數,而月份中的天數不一致。 不規則陣列也稱為陣列的陣列,專為這類案例所設計。 不規則陣列是其元素也是陣列的陣列。 不規則陣列和不規則陣列中的每個項目都可以有一或多個維度。

下列範例會使用一個月份的陣列,而該陣列的每個元素則是日期陣列。 範例使用不規則陣列,因為不同月份的天數不同。 範例示範如何建立不規則陣列、為其指派值,以及擷取和顯示其值。

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

不規則陣列是一維陣列,其元素包含陣列。 因此,Array.Length 屬性和 Array.GetLength(0) 方法會在一維陣列中傳回元素數目,並且 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

長度為零的陣列

Visual Basic 會區分未初始化的陣列 (值為 Nothing 的陣列) 與長度為零的陣列或空陣列 (沒有元素的陣列)。未初始化的陣列是尚未設定維度或未獲指派任何值的陣列。 例如:

Dim arr() As String

以 -1 的維度宣告長度為零的陣列。 例如:

Dim arrZ(-1) As String

在下列情況中,您可能需要建立長度為零的陣列:

  • 為了避免發生 NullReferenceException 例外狀況,程式碼必須存取 Array 類別的成員 (例如 LengthRank),或者呼叫 Visual Basic 函式 (例如 UBound)。

  • 您希望不需檢查 Nothing 作為特殊情況,讓程式碼更簡單。

  • 程式碼會與應用程式開發介面互動,這個介面會要求您傳遞長度為零的陣列給一個或多個程序,或從一個或多個程序傳回長度為零的陣列。

分割陣列

在某些情況下,您可能需要將單一陣列分割成多個陣列。 這牽涉到識別要分割陣列的一或多個點,然後將陣列插入兩或多個不同的陣列。

注意

本節不會討論根據一些分隔符號將單一字串分割成字串陣列。 如需分割字串的相關資訊,請參閱 String.Split 方法。

分割陣列最常見的準則如下:

  • 陣列中的項目數。 例如,您可能想要將超過指定元素數目的陣列分割成大約相等的部分。 為此,您可以使用 Array.LengthArray.GetLength 方法傳回的值。

  • 做為分隔符號的元素值,會指出應該分割陣列的位置。 您可以呼叫 Array.FindIndexArray.FindLastIndex 方法來搜尋特定值。

一旦決定應該分割陣列的索引或索引之後,就可以呼叫 Array.Copy 方法來建立個別陣列。

下列範例會將陣列分割成大小大約相等的兩個陣列。 (如果陣列元素的總數是奇數,則第一個陣列的元素數量會較第二個陣列多一個。)


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" (做為陣列分隔符號),將字串陣列分割成兩個陣列。 新的陣列並未包含其包含分隔符號的元素。


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

聯結陣列

您也可以將許多陣列組合成單一較大的陣列。 若要這樣做,您也會使用 Array.Copy 方法。

注意

本節不會討論將字串陣列聯結至單一字串。 如需聯結字串陣列的相關資訊,請參閱 String.Join 方法。

將每個陣列的元素複製到新陣列之前,您必須先確保您已初始化陣列,使其足以容納新的陣列。 您可以使用下列其中一種作法:

  • 使用 ReDim Preserve 陳述式,在將新元素新增至陣列之前,先動態展開陣列。 這是最簡單的技術,但是當您複製大型陣列時,可能會導致效能降低和記憶體耗用量過多。
  • 計算新大型陣列所需的元素總數,然後將每個來源陣列的元素新增至其中。

下列範例會使用第二個方法,將具有 10 個元素的四個陣列新增至單一陣列。

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 會建立新的陣列,並釋出前一個陣列。 這將佔用執行時間。 因此,如果您處理的項目數經常變更,或無法預測需要的最大項目數,您通常會使用集合來達到較佳的效能。

對於某些集合,您可以將索引鍵值指派給您放入集合的任何物件,讓您可以藉由使用索引鍵快速擷取物件。

如果集合包含只有一個資料類型的項目,則可使用 System.Collections.Generic 命名空間內的其中一個類別。 泛型集合會強制類型安全,如此就不會加入其他資料類型。

如需集合的詳細資訊,請參閱集合

詞彙 定義
Array Dimensions in Visual Basic 說明陣列中的順位和維度。
如何:在 Visual Basic 中初始化陣列變數 描述如何在陣列中填入初始值。
如何:在 Visual Basic 中排序陣列 示範如何依字母順序排列陣列中的項目。
如何:指派一個陣列至另一個陣列 描述將陣列指派給另一個陣列變數的規則和步驟。
針對陣列進行疑難排解 討論在使用陣列時會引發的一些常見問題。

另請參閱