Visual Basic 中的数组

数组是一组值,这些值是逻辑上相互关联的 元素。 例如,数组可能包含语法学校每个年级的学生数;数组中的每个元素都是一年级的学生数。 同样,数组可能包含学生对类的成绩;数组的每个元素都是一个级别。

可以通过单独的变量存储我们的每个数据项。 例如,如果我们的应用程序分析学生评分,则可以为每位学生的成绩使用单独的变量,如 englishGrade1 、等 englishGrade2 。此方法有三个主要限制:

  • 我们必须在设计时了解我们必须处理的成绩。
  • 处理大量成绩很快就会变得难以处理。 这进而会使应用程序更有可能出现严重错误。
  • 很难维护。 我们添加的每个新评分要求修改、重新编译和重新部署应用程序。

通过使用数组,可以按相同的名称引用这些相关的值,并使用名为 索引下标 的数字来根据元素在数组中的位置来识别单个元素。 数组的索引范围为0到数组中元素总数减1之间的值。 如果使用 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(3, 2) {{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 表示幼儿园)。

  • 元素中包含的值表示每个年级的学生数量。

显示学生数数组的关系图

下面的示例包含创建和使用数组的 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 仅扩大到 Double ,因此 Double 是基准类型。 有关详细信息,请参阅 Widening and Narrowing Conversions

备注

只能对定义为类型成员中的局部变量的数组使用类型推理。 如果不存在显式类型定义,则在类级别使用数组文本定义的数组的类型为 Object[] 。 有关详细信息,请参阅 局部类型推理

请注意,上面的示例将定义 values 为类型的数组, Double 即使所有数组文本都为类型,也是如此 Integer 。 你可以创建此数组,因为数组文本中的值可以扩大到 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}}

使用嵌套的数组文本创建和填充数组时,如果嵌套数组文本中的元素数目不匹配,则会发生错误。 如果显式声明数组变量的维数不同于数组文本,也会出现错误。

正如可以对一维数组使用的一样,在使用嵌套的数组文本创建多维数组时,可以依赖类型推理。 推断出的类型是所有嵌套级别的所有数组文本中的所有值的基准类型。 下面的示例 Double[,] 从类型为和的值创建一个类型为的二维数组 Integer Double

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

有关其他示例,请参阅如何:在 Visual Basic 中初始化数组变量

循环访问数组

循环访问数组时,可将数组中的每个元素从最小索引访问到最高级别或从最高到最低。 通常,使用 For .。。下一语句每个 .。。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...NextGetUpperBound 方法具有用于指定维度的参数。 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

数组大小

数组的大小是数组所有维度的长度的产物。 它表示数组中当前所包含的元素总数。 例如,下面的示例声明一个二维数组,每个维度中包含四个元素。 如示例中的输出所示,数组的大小为 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
大小和元素大小 数组的大小独立于其元素的数据类型。 大小始终表示元素总数,而不是在内存中使用的字节数。
内存消耗 做出关于数组如何存储在内存中的假设是不可靠的。 由于不同数据宽度的平台上的存储会有所变化,因此同一数组在 64 位系统上可以占用比在 32 位系统上更多的内存。 具体取决于数组初始化时的系统配置,公共语言运行时 (CLR) 可以尽可能地将存储分配到靠近包元素的地方,或者将它们全部在自然硬件边界上对齐。 此外,数组需要存储开销的控制信息,而且每添加一个维度,这种开销随之增加。

数组类型

每个数组都具有一个数据类型,该数据类型不同于其元素的数据类型。 没有一种数据类型能用于所有数组。 相反,数组的数据类型由数组的维度数量或 “排名”,以及数组中元素的数据类型确定。 只有当两个数组变量具有相同的秩并且它们的元素具有相同的数据类型时,它们才具有相同的数据类型。 数组的维度长度不会影响数组数据类型。

每个数组都继承自 System.Array 类,并且你可以声明一个类型为 Array 的变量,但不能创建一个类型为 Array 的数组。 例如,虽然下面的代码将变量声明 arr 为类型 Array 并调用 Array.CreateInstance 方法来实例化数组,但数组的类型会证明是对象 []。


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 语句中,添加不带括号的局部数组变量。

若要将作为参数的数组指定到 SubFunction 步骤中,可将此参数定义为具有指定数据类型和维度数量的数组。 在对过程的调用中,传递具有相同数据类型和维度数量的数组变量。

在下面的示例中, GetNumbers 函数返回一个 Integer() 类型为的一维数组 IntegerShowNumbers 过程接受 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(,) 类型为的二维数组 IntegerShowNumbersMultiDim 过程接受 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 异常,你的代码必须访问类的成员( ArrayLengthRank ),或调用 Visual Basic 函数(如) UBound

  • 您希望通过无需将作为特殊情况进行检查来简化您的代码 Nothing

  • 你的代码与应用程序编程接口 (API) 交互,该接口要求你将一个零长度数组传递到一个或多个过程,或将一个零长度数组返回到一个或多个过程。

拆分数组

在某些情况下,可能需要将单个数组拆分为多个数组。 这涉及到识别要拆分数组的点,然后将该数组 spitting 为两个或多个单独的数组。

备注

本部分不讨论根据某些分隔符将单个字符串拆分为字符串数组。 有关拆分字符串的信息,请参阅 String.Split 方法。

拆分数组最常见的条件是:

  • 数组中的元素数。 例如,你可能想要将多个指定数量的元素的数组拆分为一些大致相等的部分。 为此,可以使用或方法返回的值 Array.Length Array.GetLength

  • 元素的值,它用作指示应拆分数组的位置的分隔符。 可以通过调用和方法搜索特定值 Array.FindIndex Array.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 将新元素添加到数组之前,请使用语句动态展开数组。 这是最简单的方法,但它可能会导致性能下降,并在复制大型数组时消耗过多的内存。
  • 计算新的大型数组所需的元素总数,然后将每个源数组的元素添加到其中。

下面的示例使用第二种方法将四个数组分别添加到一个数组中。

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 而动态增长和收缩。

使用 对数组进行重新Visual Basic,将创建一个新数组并释放 ReDim 上一个数组。 这需要执行时间。 因此,如果处理的项目数频繁更改,或者无法预测所需的最大项数,则通常使用 集合可以获得更好的性能。

对于某些集合,你可以为放入集合中的任何对象分配一个密钥,这样你便可以使用该密钥快速检索此对象。

如果集合中只包含一种数据类型的元素,则可以使用 System.Collections.Generic 命名空间中的一个类。 泛型集合强制类型安全,因此无法向其添加任何其他数据类型。

有关集合的详细信息,请参阅集合

术语 定义
Array Dimensions in Visual Basic 在数组中解释级别和维度。
如何:在 Visual Basic 中初始化数组变量 说明如何用初始值填充数组。
如何:在 Visual Basic 中对数组进行排序 显示如何按字母先后顺序对数组元素进行排序。
如何:将一个数组赋给另一个数组 说明将数组分配到另一个数组变量的规则和步骤。
数组疑难解答 讨论在使用数组时出现的一些常见问题。

另请参阅