Visual Basic 中的数组

数组是一组称为元素的值,这些 在逻辑上彼此相关。 例如,数组可能包含语法学校中每个年级的学生数;数组的每个元素都是单个年级的学生数。 同样,数组可能包含学生对班级的成绩;数组的每个元素都是一个等级。

可以使用各个变量来存储每个数据项。 例如,如果应用程序分析学生成绩,则可以为每个学生的成绩使用单独的变量,例如 englishGrade1englishGrade2等等。此方法有三个主要限制:

  • 在设计时必须确切地知道我们必须处理多少个成绩等级。
  • 很难快速处理大量的成绩等级。 这反过来又使应用程序更有可能有严重的 bug。
  • 很难维护。 我们添加的每个新等级都需要修改、重新编译和重新部署应用程序。

通过使用数组,可以按同名引用这些相关值,并使用一个名为 索引下标 的数字根据其在数组中的位置标识单个元素。 数组的索引范围从 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(,) {{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。 例如,如果提供给数组字面量的值列表包含Integer类型、Long类型 和 Double类型的值,那么生成的数组的类型为Double。 因为 IntegerLong 只扩大到 DoubleDouble 是主导类型。 有关详细信息,请参阅 “扩大和缩小转换”。

注释

只能对类型成员中定义为局部变量的数组使用类型推理。 如果不存在显式类型定义,则类级别使用数组文本定义的数组的类型为类型 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}}

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

如同创建一维数组时一样,在使用嵌套数组文本创建多维数组时,可以依赖类型推理。 推理出的类型是用于所有嵌套级别的所有数组文本中的所有值的主控类型。 以下示例使用类型为 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

数组大小

数组的大小是其所有维度长度的乘积。 它表示数组中当前包含的元素总数。 例如,以下示例声明一个二维数组,其中包含每个维度中的四个元素。 如示例中的输出所示,数组的大小为 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

注释

此数组大小的讨论不适用于交错数组。 有关交错数组并确定交错数组的大小的信息,请参阅 “Jagged 数组” 部分。

可以使用该 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)可以将存储分配到尽可能接近的元素,或将它们全部对齐在自然硬件边界上。 此外,数组在保存控制信息时需要额外的存储开销,并且每增加一个维度,这种开销就会增加。

数组类型

每个数组都有一个数据类型,该数据类型与其元素的数据类型不同。 所有数组都没有单个数据类型。 相反,数组的数据类型由数组的维度数或 排名以及数组中元素的数据类型决定。 仅当两个数组变量具有相同的排名并且其元素具有相同的数据类型时,两个数组变量才属于同一数据类型。 数组维度的长度不会影响数组数据类型。

每个数组都继承自 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 语句中,包含不带括号的局部数组变量。

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

在下面的示例中,该 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

在以下情况下,可能需要创建零长度数组:

  • 在不引发异常的情况下,代码必须访问 Array 类的成员,例如 LengthRank,或调用 Visual Basic 函数,例如 UBound

  • 无需出于特殊情况检查 Nothing,这样可以保持代码的简单性。

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

拆分数组

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

注释

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

拆分数组的最常见条件包括:

  • 数组中的元素数。 例如,你可能想要将多个多个元素的数组拆分为多个近似相等的部分。 为此,您可以使用Array.Length方法或Array.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 其中一个类。 泛型集合强制实施类型安全性,以便无法向其中添加其他数据类型。

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

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

另请参阅