Visual Basic 中的数组Arrays in Visual Basic

数组是一组逻辑相关的值,术语上称之为“元素”。 An array is a set of values, which are termed elements, that are logically related to each other. 例如,数组可能包含一个语法学校中每个年级的学生数量;数组的每个元素则是单个年级的学生数量。For example, an array may consist of the number of students in each grade in a grammar school; each element of the array is the number of students in a single grade. 同样,数组可能包含的一个班的学生的成绩;数组的每个元素则是一个成绩。Similarly, an array may consist of a student's grades for a class; each element of the array is a single grade.

可以使用单独的变量来存储每个数据项。It is possible individual variables to store each of our data items. 例如,如果应用程序分析学生成绩,则可以使用单独的变量表示每个学生的成绩,如 englishGrade1englishGrade2 等等。此方法具有三个主要的限制:For example, if our application analyzes student grades, we can use a separate variable for each student's grade, such as englishGrade1, englishGrade2, etc. This approach has three major limitations:

  • 我们在设计时必须知道我们需要处理的成绩的总数。We have to know at design time exactly how many grades we have to handle.
  • 处理大量的成绩可导致速度变慢。Handling large numbers of grades quickly becomes unwieldy. 反过来,这会使应用程序更有可能出现严重的 bug。This in turn makes an application much more likely to have serious bugs.
  • 很难维护。It is difficult to maintain. 我们添加的每个新成绩都要求应用程序进行修改、重新编译和重新部署。Each new grade that we add requires that the application be modified, recompiled, and redeployed.

通过使用数组,可以使用相同的名称代指这些相关值,并使用一个称为“索引”或“下标”的数字来基于各个元素在数组中的位置对其进行标识。 By using an array, you can refer to these related values by the same name, and use a number that’s called an index or subscript to identify an individual element based on its position in the array. 数组索引的范围是从 0 到数组中的总元素数 - 1。The indexes of an array range from 0 to one less than the total number of elements in the array. 当使用 Visual Basic 语法来定义数组的大小时,指定的是其最高的索引值,而不是数组中元素的总数。When you use Visual Basic syntax to define the size of an array, you specify its highest index, not the total number of elements in the array. 可以使用数组作为一个单元,利用循环迭代其元素的功能,你将无需在设计时了解数组确切包含多少个元素。You can work with the array as a unit, and the ability to iterate its elements frees you from needing to know exactly how many elements it contains at design time.

在进行说明之前,请看几个简单的示例:Some quick examples before explanation:

' 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)() {}

简单数组中的数组元素Array elements in a simple array

我们创建一个名为 students 的数组来存储语法学校中每个年级的学生数量。Let's create an array named students to store the number of students in each grade in a grammar school. 元素的索引范围为 0 到 6。The indexes of the elements range from 0 through 6. 使用此数组比声明七个变量更简单。Using this array is simpler than declaring seven variables.

下图显示students数组。The following illustration shows the students array. 对于数组的每个元素:For each element of the array:

  • 元素索引表示年级(索引 0 表示幼儿园)。The index of the element represents the grade (index 0 represents kindergarten).

  • 元素中包含的值表示每个年级的学生数量。The value that’s contained in the element represents the number of students in that grade.

显示学生人数的数组的关系图

下面的示例包含用于创建和使用数组的 Visual Basic 代码:The following example contains the Visual Basic code that creates and uses the array:


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

该示例执行三项操作:The example does three things:

  • 声明了具有七个元素的数组 studentsIt declares a students array with seven elements. 数组声明中的数字 6 表示数组中的最后一个索引;它小于数组中的元素数。The number 6 in the array declaration indicates the last index in the array; it is one less than the number of elements in the array.
  • 它将值分配给数组中的每个元素。It assigns values to each element in the array. 通过使用数组名称并在括号中包含单个元素的索引访问数组元素。Array elements are accessed by using the array name and including the index of the individual element in parentheses.
  • 列出了数组的每个值。It lists each value of the array. 该示例使用 For 语句来按索引号访问数组的每个元素。The example uses a For statement to access each element of the array by its index number.

前面的示例中的数组 students 是一维数组,因为它使用一个索引。The students array in the preceding example is a one-dimensional array because it uses one index. 使用多个索引或下标的数组称为“多维” 。An array that uses more than one index or subscript is called multidimensional. 有关详细信息,请参阅本文的其余部分和 Visual Basic 中的数组维度For more information, see the rest of this article and Array Dimensions in Visual Basic.

创建数组Creating an array

以下几种方式,可以定义数组的大小:You can define the size of an array in several ways:

  • 当声明数组时,可以指定大小:You can specify the size when the array is declared:

    ' 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 子句提供数组大小:You can use a New clause to supply the size of an array when it’s created:

    ' 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 语句来重新定义其大小。If you have an existing array, you can redefine its size by using the ReDim statement. 可以指定 ReDim 语句保留数组中的值,也可以指定它创建空数组。You can specify that the ReDim statement keep the values that are in the array, or you can specify that it create an empty array. 下面的示例演示了用 ReDim 语句来修改现有数组的大小的不同用法。The following example shows different uses of the ReDim statement to modify the size of an existing array.

' 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 语句For more information, see the ReDim Statement.

将值存储在数组Storing values in an array

你可以通过使用类型 Integer的索引访问数组中的每个位置。You can access each location in an array by using an index of type Integer. 你可以使用括号内的索引来引用每个数组位置,从而存储和检索数组中的值。You can store and retrieve values in an array by referencing each array location by using its index enclosed in parentheses. 对于多维数组的索引用逗号 (,) 分隔。Indexes for multidimensional arrays are separated by commas (,). 每个数组维度都需要一个索引。You need one index for each array dimension.

下面的示例演示用于存储和检索值在数组中的一些语句。The following example shows some statements that store and retrieve values in arrays.


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

使用数组文本填充数组Populating an array with array literals

通过使用数组文本,可以在创建它时填充具有一组初始值的数组。By using an array literal, you can populate an array with an initial set of values at the same time that you create it. 数组文本包含用逗号分隔的值列表,这些值被括在括号内 ({})。An array literal consists of a list of comma-separated values that are enclosed in braces ({}).

通过使用数组文本创建数组时,可以提供数组类型或使用类型推理功能来确定数组类型。When you create an array by using an array literal, you can either supply the array type or use type inference to determine the array type. 下面的示例显示了这两个选项。The following example shows both options.

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

使用类型推理时,数组的类型由文本值列表中的“基准类型”决定。 When you use type inference, the type of the array is determined by the dominant type in the list of literal values. 基准类型是数组中的所有其他类型可以扩大到的类型。The dominant type is the type to which all other types in the array can widen. 如果无法确定此唯一类型,基准类型将是数组中所有其他类型可以缩小到的唯一类型。If this unique type can’t be determined, the dominant type is the unique type to which all other types in the array can narrow. 如果这两种唯一类型都无法确定,则基准类型是 ObjectIf neither of these unique types can be determined, the dominant type is Object. 例如,如果提供给数组文本的值列表包含 IntegerLongDouble 类型的值,则生成的数组类型是 DoubleFor example, if the list of values that’s supplied to the array literal contains values of type Integer, Long, and Double, the resulting array is of type Double. 因为 IntegerLong 仅能扩大到 Double,因此 Double是基准类型。Because Integer and Long widen only to Double, Double is the dominant type. 有关详细信息,请参阅扩大和缩小转换For more information, see Widening and Narrowing Conversions.

备注

仅对定义为本地变量的类型成员的数组,可以使用类型推理。You can use type inference only for arrays that are defined as local variables in a type member. 如果缺少显式类型定义,则数组使用数组文本在类级别定义的类型是Object[]If an explicit type definition is absent, arrays defined with array literals at the class level are of type Object[]. 有关详细信息,请参阅局部类型推理For more information, see Local type inference.

请注意,上面的示例将 values 定义为 Double 类型的数组,即使所有数组文本都属于 Integer 类型也是如此。Note that the previous example defines values as an array of type Double even though all the array literals are of type Integer. 可以创建此数组,因为数组文本中的值可以扩大到 Double 值。You can create this array because the values in the array literal can widen to Double values.

此外可以创建并使用填充多维数组嵌套数组文本You can also create and populate a multidimensional array by using nested array literals. 嵌套的数组文本必须具有与生成的数组保持一致维度的数。Nested array literals must have a number of dimensions that’s consistent with the resulting array. 下面的示例使用嵌套的数组文本创建一个二维整数的数组。The following example creates a two-dimensional array of integers by using nested array literals.

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

在使用嵌套的数组文本创建并填充数组时,如果嵌套的数组文本中的元素数不匹配,就会出错。When using nested array literals to create and populate an array, an error occurs if the number of elements in the nested array literals don't match. 如果显式声明数组变量时数组文本具有不同数量的维度,也会发生错误。An error also occurs if you explicitly declare the array variable to have a different number of dimensions than the array literals.

与处理一维数组相同,使用嵌套的数组文本创建多维数组时,也可以依赖于类型推断。Just as you can for one-dimensional arrays, you can rely on type inference when creating a multidimensional array with nested array literals. 推断出的类型是所有嵌套级别的所有数组文本中的所有值的基准类型。The inferred type is the dominant type for all the values in all the array literals for all nesting level. 下面的示例从 IntegerDouble 类型的值中创建一个 Double[,] 类型的二维数组。The following example creates a two-dimensional array of type Double[,] from values that are of type Integer and Double.

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

有关其他示例,请参阅如何:在 Visual Basic 中初始化数组变量For additional examples, see How to: Initialize an Array Variable in Visual Basic.

循环访问数组Iterating through an array

当循环访问数组时,将按从最低到最高或从最高到低的索引顺序访问数组中的每个元素。When you iterate through an array, you access each element in the array from the lowest index to the highest or from the highest to the lowest. 通常情况下,使用 For...Next 语句For Each...Next 语句循环访问数组的元素。Typically, use either the For...Next Statement or the For Each...Next Statement to iterate through the elements of an array. 如果不知道数组的最高值,则可以调用 Array.GetUpperBound 方法来获取索引的最高值。When you don't know the upper bounds of the array, you can call the Array.GetUpperBound method to get the highest value of the index. 尽管最小索引值几乎始终为 0,但可以调用 Array.GetLowerBound 方法来获取索引的最小值。Although lowest index value is almost always 0, you can call the Array.GetLowerBound method to get the lowest value of the index.

下面的示例通过使用 For...Next 语句循环访问一维数组。The following example iterates through a one-dimensional array by using the For...Next statement.


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 语句循环访问多维数组。The following example iterates through a multidimensional array by using a For...Next statement. GetUpperBound 方法具有用于指定维度的参数。The GetUpperBound method has a parameter that specifies the dimension. GetUpperBound(0) 返回第一个维度的最高索引,GetUpperBound(1) 返回第二个维度的最高索引。GetUpperBound(0) returns the highest index of the first dimension, and GetUpperBound(1) returns the highest index of the second dimension.


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 语句循环访问一个一维数组和一个二维数组。The following example uses a For Each...Next Statementto iterate through a one-dimensional array and a two-dimensional array.


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

数组大小Array size

数组的大小是数组所有维度的长度的乘积。The size of an array is the product of the lengths of all its dimensions. 它表示数组中当前所包含的元素总数。It represents the total number of elements currently contained in the array. 例如,下面的示例声明每个维度中包含四个元素的二维数组。For example, the following example declares a 2-dimensional array with four elements in each dimension. 如示例输出所示,该数组的大小为 16 (或 (3 + 1) * (3 + 1)。As the output from the example shows, the array's size is 16 (or (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

备注

数组大小的这一讨论不适用于交错数组。This discussion of array size does not apply to jagged arrays. 交错的数组并确定交错数组的大小的信息,请参阅交错数组部分。For information on jagged arrays and determining the size of a jagged array, see the Jagged arrays section.

可以通过使用 Array.Length 属性查找数组大小。You can find the size of an array by using the Array.Length property. 可以通过使用 Array.GetLength 方法查找多维数组的每个维度的长度。You can find the length of each dimension of a multidimensional array by using the Array.GetLength method.

要想调整数组变量的大象,可为其分配新的数组对象,或使用 ReDim语句 语句。You can resize an array variable by assigning a new array object to it or by using the ReDim Statement statement. 下面的示例使用 ReDim 语句将具有 100 个元素的数组更改为具有 50 个元素的数组。The following example uses the ReDim statement to change a 100-element array to a 51-element array.


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

 

当处理数组大小时,需要记住几件事情。There are several things to keep in mind when dealing with the size of an array.

维度长度Dimension Length 每个维度的索引均从 0 开始,这意味着其范围为 0 到其上限之间。The index of each dimension is 0-based, which means it ranges from 0 to its upper bound. 因此,给定维度的长度大于该维度的声明的上限。Therefore, the length of a given dimension is one greater than the declared upper bound of that dimension.
长度限制Length Limits 数组每个维度的长度限制为 Integer 数据类型的最大值,即 Int32.MaxValue 或 (2 ^31) - 1。The length of every dimension of an array is limited to the maximum value of the Integer data type, which is Int32.MaxValue or (2 ^ 31) - 1. 但是,数组的总大小还受到系统上可用内存的限制。However, the total size of an array is also limited by the memory available on your system. 如果尝试初始化超出可用内存量的数组,则运行时会引发 OutOfMemoryExceptionIf you attempt to initialize an array that exceeds the amount of available memory, the runtime throws an OutOfMemoryException.
大小和元素大小Size and Element Size 数组的大小独立于其元素的数据类型。An array's size is independent of the data type of its elements. 大小始终表示元素的总数,而不是所占用的内存的字节数。The size always represents the total number of elements, not the number of bytes that they consume in memory.
内存消耗Memory Consumption 对于针对数组在内存中的存储情况进行假设,这种做法不可靠的。It is not safe to make any assumptions regarding how an array is stored in memory. 由于不同数据宽度的平台上的存储会有所变化,因此同一数组在 64 位系统上可能比在 32 位系统上占用更多内存。Storage varies on platforms of different data widths, so the same array can consume more memory on a 64-bit system than on a 32-bit system. 基于初始化数组时的系统配置,公共语言运行时 (CLR) 可能会分配存储空间以尽可能近地将元素打包在一起,或者将它们全部在自然硬件边界上对齐。Depending on system configuration when you initialize an array, the common language runtime (CLR) can assign storage either to pack elements as close together as possible, or to align them all on natural hardware boundaries. 此外,数组需要用于其控制信息的存储开销,此开销会在每次增加维度时随之增加。Also, an array requires a storage overhead for its control information, and this overhead increases with each added dimension.

数组类型The array type

每个数组的数据类型均不同于其元素的数据类型。Every array has a data type, which differs from the data type of its elements. 没有一种数据类型能用于所有数组。There is no single data type for all arrays. 相反,数组的数据类型由数组的维度数量(或者说“秩”)以及数组中元素的数据类型所决定。 Instead, the data type of an array is determined by the number of dimensions, or rank, of the array, and the data type of the elements in the array. 仅当两个数组具有相同的秩并且其元素具有相同的数据类型时,两个数组变量才具有相同的数据类型。Two array variables are of the same data type only when they have the same rank and their elements have the same data type. 数组的维度的长度不会影响数组的数据类型。The lengths of the dimensions of an array do not influence the array data type.

每个数组都继承自 System.Array 类,并且可以声明类型为 Array 的变量,但不能创建类型为 Array 的数组。Every array inherits from the System.Array class, and you can declare a variable to be of type Array, but you cannot create an array of type Array. 例如,虽然下面的代码声明 arr 变量的类型为 Array,并调用Array.CreateInstance 方法以实例化数组,但该数组的实际类型是 Object []。For example, although the following code declares the arr variable to be of type Array and calls the Array.CreateInstance method to instantiate the array, the array's type proves to be 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 的变量执行运算。Also, the ReDim Statement cannot operate on a variable declared as type Array. 出于这些原因,以及为了保证类型安全,建议将每个数组声明为特定类型。For these reasons, and for type safety, it is advisable to declare every array as a specific type.

可以通过几种方式确定数组及其元素的数据类型。You can find out the data type of either an array or its elements in several ways.

  • 可以调用 GetType 方法来获取表示变量的运行时类型的 Type 对象。You can call the GetType method on the variable to get a Type object that represents the run-time type of the variable. Type 对象可在其属性和方法中保存大量信息。The Type object holds extensive information in its properties and methods.
  • 可以将该变量传递到 TypeName 函数以获取具有该运行时类型的名称的 StringYou can pass the variable to the TypeName function to get a String with the name of run-time type.

下面的示例调用 GetType 方法和 TypeName 函数来确定数组的类型。The following example calls the both the GetType method and the TypeName function to determine the type of an array. 数组类型是 Byte(,)The array type is Byte(,). 请注意,Type.BaseType 属性还指示字节数组的基类型是 Array 类。Note that the Type.BaseType property also indicates that the base type of the byte array is the Array class.


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(,)


数组作为返回值和参数Arrays as return values and parameters

若要通过 Function 过程返回数组,请将数组数据类型和维度数指定为 Function 语句的返回类型 。To return an array from a Function procedure, specify the array data type and the number of dimensions as the return type of the Function Statement. 在函数内,声明一个具有相同数据类型和维度数的局部数组变量。Within the function, declare a local array variable with same data type and number of dimensions. Return 语句中,包含该局部数组变量(不带括号)。In the Return Statement, include the local array variable without parentheses.

若要将数组指定为 SubFunction 过程的参数,可将此参数定义为具有指定数据类型和维度数的数组。To specify an array as a parameter to a Sub or Function procedure, define the parameter as an array with a specified data type and number of dimensions. 在对该过程的调用中,传递一个具有相同数据类型和维度数的数组变量。In the call to the procedure, pass an array variable with the same data type and number of dimensions.

在以下示例中,GetNumbers函数返回Integer(),类型的一维数组IntegerIn the following example, the GetNumbers function returns an Integer(), a one-dimensional array of type Integer. ShowNumbers 过程接受 Integer() 参数。The ShowNumbers procedure accepts an Integer() argument.


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(,),类型的二维数组IntegerIn the following example, the GetNumbersMultiDim function returns an Integer(,), a two-dimensional array of type Integer. ShowNumbersMultiDim 过程接受 Integer(,) 参数。The ShowNumbersMultiDim procedure accepts an Integer(,) argument.


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

交错数组Jagged arrays

有时应用程序中的数据结构是二维而不是矩形。Sometimes the data structure in your application is two-dimensional but not rectangular. 例如,可能会使用数组来存储当月每天高温的相关数据。For example, you might use an array to store data about the high temperature of each day of the month. 该数组的第一个维度表示月份,而第二个维度表示天数,并且一个月内的天数是不一致的。The first dimension of the array represents the month, but the second dimension represents the number of days, and the number of days in a month is not uniform. “交错数组”(也称为“数组的数组”)就是专为此类方案而设计的。 A jagged array, which is also called an array of arrays, is designed for such scenarios. 交错数组的元素也是数组。A jagged array is an array whose elements are also arrays. 交错数组及其中的每个元素都可以具有一个或多个维度。A jagged array and each element in a jagged array can have one or more dimensions.

以下示例使用月份数组,其中每个元素是天数数组。The following example uses an array of months, each element of which is an array of days. 该示例使用交错数组,因为不同月份有不同的天数。The example uses a jagged array because different months have different numbers of days. 示例演示如何创建交错数组,将值分配给它,并检索和显示它的值。The example shows how to create a jagged array, assign values to it, and retrieve and display its values.

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 循环将值分配给交错数组(以逐个元素为基础)。The previous example assigns values to the jagged array on an element-by-element basis by using a For...Next loop. 通过使用嵌套的数组文本,还可以将值分配给交错数组的元素。You can also assign values to the elements of a jagged array by using nested array literals. 但是,尝试使用嵌套数组文本 (例如,Dim valuesjagged = {{1, 2}, {2, 3, 4}}) 会生成编译器错误 BC30568However, the attempt to use nested array literals (for example, Dim valuesjagged = {{1, 2}, {2, 3, 4}}) generates compiler error BC30568. 若要更正此错误,请将内部数组文本用括号括起来。To correct the error, enclose the inner array literals in parentheses. 圆括号会强制计算数组文本表达式,生成的值会用于外部数组文本,如以下示例所示。The parentheses force the array literal expression to be evaluated, and the resulting values are used with the outer array literal, as the following example shows.


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

交错数组是一维数组,其元素包含数组。A jagged array is a one-dimensional array whose elements contain arrays. 因此,Array.Length 属性和 Array.GetLength(0) 方法会返回这个一维数组的元素数,并且 Array.GetLength(1) 会引发 IndexOutOfRangeException,因为交错数组不是多维数组。Therefore, the Array.Length property and the Array.GetLength(0) method return the number of elements in the one-dimensional array, and Array.GetLength(1) throws an IndexOutOfRangeException because a jagged array is not multidimensional. 通过检索每个子数组的 Array.Length 属性可确定每个子数组中的元素数。You determine the number of elements in each subarray by retrieving the value of each subarray's Array.Length property. 下面的示例说明了如何确定交错数组中的元素数。The following example illustrates how to determine the number of elements in a jagged array.


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

零长度数组Zero-length arrays

Visual Basic 区分未初始化的数组(其值是Nothing)和“零长度数组”或空数组(不包含任何元素)。 未初始化的数组不会被确定维度或被赋值。Visual Basic differentiates between a uninitialized array (an array whose value is Nothing) and a zero-length array or empty array (an array that has no elements.) An uninitialized array is one that has not been dimensioned or had any values assigned to it. 例如:For example:

Dim arr() As String

零长度数组的声明维度为 -1。A zero-length array is declared with a dimension of -1. 例如:For example:

Dim arrZ(-1) As String

在下列情况下,你可能需要创建一个零长度数组:You might need to create a zero-length array under the following circumstances:

  • 在不引发 NullReferenceException 异常的前提下,你的代码必须访问 Array 类的成员,如 LengthRank,或调用 Visual Basic 函数,例如 UBoundWithout risking a NullReferenceException exception, your code must access members of the Array class, such as Length or Rank, or call a Visual Basic function such as UBound.

  • 你想要保持代码简洁,而不必检查特殊情况 NothingYou want to keep your code simple by not having to check for Nothing as a special case.

  • 你的代码与应用程序编程接口 (API) 交互,该接口要求你将一个零长度数组传递到一个或多个过程,或将一个零长度数组返回到一个或多个过程。Your code interacts with an application programming interface (API) that either requires you to pass a zero-length array to one or more procedures or returns a zero-length array from one or more procedures.

拆分数组Splitting an array

在某些情况下,可能需要将单个数组拆分为多个数组。In some cases, you may need to split a single array into multiple arrays. 这涉及到确定数组的一个或多个分割点,然后将数组分割为两个或更多的数组。This involves identifying the point or points at which the array is to be split, and then spitting the array into two or more separate arrays.

备注

本部分不讨论如何将单个字符串基于某些分隔符拆分为字符串数组。This section does not discuss splitting a single string into a string array based on some delimiter. 有关拆分字符串的信息,请参阅 String.Split 方法。For information on splitting a string, see the String.Split method.

用于拆分数组的最常见条件是:The most common criteria for splitting an array are:

  • 数组中的元素数。The number of elements in the array. 例如,你可能想要将一个元素数超过指定值的数组拆分为多个大小大致相等的数组。For example, you might want to split an array of more than a specified number of elements into a number of approximately equal parts. 为此,可以使用以下任一方法的返回值:Array.LengthArray.GetLength 方法。For this purpose, you can use the value returned by either the Array.Length or Array.GetLength method.

  • 元素的值,该值充当分隔符,用于指示数组的分割点。The value of an element, which serves as a delimiter that indicates where the array should be split. 可以通过调用 Array.FindIndexArray.FindLastIndex 方法来搜索特定值。You can search for a specific value by calling the Array.FindIndex and Array.FindLastIndex methods.

一旦确定了拆分数组的一个或多个索引位置,之后即可通过调用 Array.Copy 方法来创建各个数组。Once you've determined the index or indexes at which the array should be split, you can then create the individual arrays by calling the Array.Copy method.

下面的示例将数组拆分成两个大小大致相等的数组。The following example splits an array into two arrays of approximately equal size. (如果数组元素的总数为奇数,则第一个数组比第二个数组多一个元素。)(If the total number of array elements is odd, the first array has one more element than the second.)


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”的元素(充当数组分隔符)的存在情况将一个字符串数组拆分成两个数组。The following example splits a string array into two arrays based on the presence of an element whose value is "zzz", which serves as the array delimiter. 新数组不包括包含分隔符的元素。The new arrays do not include the element that contains the delimiter.


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

合并数组Joining arrays

还可以将多个数组合并为一个较大的数组。You can also combine a number of arrays into a single larger array. 若要执行此操作,仍可使用 Array.Copy 方法。To do this, you also use the Array.Copy method.

备注

本部分不讨论将单个字符串联接到单个字符串的相关信息。This section does not discuss joining a string array into a single string. 有关联接字符串数组的信息,请参阅 String.Join 方法。For information on joining a string array, see the String.Join method.

在将每个数组的元素复制到新数组前,首先必须确保已初始化了该数组,确保它有足够的空间来容纳新数组。Before copying the elements of each array into the new array, you must first ensure that you have initialized the array so that it is large enough to accommodate the new array. 可以通过两种方法执行此操作:You can do this in one of two ways:

  • 使用 ReDim Preserve 语句,以便在向数组添加新元素之前将其动态扩大。Use the ReDim Preserve statement to dynamically expand the array before adding new elements to it. 这是最简单的方法,但在复制大型数组时可能会导致性能下降并占用过多内存。This is the easiest technique, but it can result in performance degradation and excessive memory consumption when you are copying large arrays.
  • 计算新大型数组所需的元素总数,然后将每个源数组的元素添加到其中。Calculate the total number of elements needed for the new large array, then add the elements of each source array to it.

以下示例使用第二种方法将分别具有 10 个元素的四个数组添加到一个数组中。The following example uses the second approach to add four arrays with ten elements each to a single array.

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.

因为在这种情况下源数组也是所有小型,我们还可以动态地可以展开数组,我们将每个新数组的元素添加到它。Since in this case the source arrays are all small, we can also dynamically expand the array as we add the elements of each new array to it. 以下示例执行该操作。The following example does that.

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.

作为数组的替代方法的集合Collections as an alternative to arrays

数组最适用于创建和使用固定数量的强类型化对象。Arrays are most useful for creating and working with a fixed number of strongly typed objects. 集合提供更灵活的方式来使用对象组。Collections provide a more flexible way to work with groups of objects. 数组需要显式使用ReDim语句来更改其大小,与此不同,集合可随着应用程序更改的需求进行动态扩大和缩小。Unlike arrays, which require that you explicitly change the size of an array with the ReDim Statement, collections grow and shrink dynamically as the needs of an application change.

当使用 ReDim 来重新设置数组的维度时,Visual Basic 会创建一个新数组,并释放前一个数组。When you use ReDim to redimension an array, Visual Basic creates a new array and releases the previous one. 这需要执行时间。This takes execution time. 因此,如果需要频繁进行更改,或者不能预测所需的最大项数,则通常应使用集合来获得更好的性能。Therefore, if the number of items you are working with changes frequently, or you cannot predict the maximum number of items you need, you'll usually obtain better performance by using a collection.

对于某些集合,你可以为放入集合中的任何对象分配一个关键字,这样你便可以使用该关键字快速检索此对象。For some collections, you can assign a key to any object that you put into the collection so that you can quickly retrieve the object by using the key.

如果你的集合中只包含一种数据类型的元素,你可以使用 System.Collections.Generic 命名空间中的一个类。If your collection contains elements of only one data type, you can use one of the classes in the System.Collections.Generic namespace. 泛型集合强制类型安全,因此无法向其添加任何其他数据类型。A generic collection enforces type safety so that no other data type can be added to it.

有关集合的详细信息,请参阅集合For more information about collections, see Collections.

术语Term 定义Definition
Visual Basic 中的数组维度Array Dimensions in Visual Basic 解释数组中的秩和维度。Explains rank and dimensions in arrays.
如何:在 Visual Basic 中初始化数组变量How to: Initialize an Array Variable in Visual Basic 说明如何用初始值填充数组。Describes how to populate arrays with initial values.
如何:在 Visual Basic 中对数组进行排序How to: Sort An Array in Visual Basic 演示如何按字母先后顺序对数组元素进行排序。Shows how to sort the elements of an array alphabetically.
如何:将一个数组赋给另一个数组How to: Assign One Array to Another Array 说明将数组分配到另一个数组变量的规则和步骤。Describes the rules and steps for assigning an array to another array variable.
数组疑难解答Troubleshooting Arrays 讨论在使用数组时出现的一些常见问题。Discusses some common problems that arise when working with arrays.

请参阅See also