数组 (Visual Basic)

“数组”是一组逻辑上相互关联的值,例如初级学校每个年级的学生数。

通过使用数组,您可以通过同一名称来引用这些相关的值,并使用一个称为“索引”或“下标”的数字来区分这些值。 每个值称为数组的“元素”。 这些值是连续的,从索引 0 一直到最大索引值。

与数组相反,包含单个值的变量称为标量变量。

主题内容

  • 简单数组中的数组元素

  • 创建数组

  • 声明数组

  • 在数组中存储值

  • 用初始值填充数组

    • 嵌套的数组文本
  • 通过数组迭代

  • 作为返回值和参数的数组

  • 交错数组

  • 零长度数组

  • 数组大小

  • 数组类型和其他类型

  • 使用集合替代数组

简单数组中的数组元素

下面的示例声明一个数组变量来存储初级学校每个年级的学生数。

Dim students(6) As Integer

前面的示例中的数组 students 包含 7 个元素。 元素的索引范围为从 0 到 6。 此数组比声明 7 个变量更简单。

下图显示了数组 students。 对于数组的每个元素:

  • 元素索引表示年级(索引 0 表示幼儿园)。

  • 包含在元素中的值表示该年级的学生数。

"students" 数组的元素

图:显示学生数的数组

下面的示例显示了如何引用 students 数组的第一个、第二个和最后一个元素。

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

可以只通过使用数组变量名(没有索引),将数组作为一个整体引用。

前面示例中的数组 students 使用一个索引,因此称为一维。 使用多个索引或下标的数组称为“多维”。 有关更多信息,请参阅本主题的剩余部分和 Visual Basic 中的数组维数

创建数组

您可以使用几种方法来定义数组大小。 可以在声明数组时提供大小,如下面的示例所示。

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

也可以在创建数组时使用 New 子句提供其大小,如下面的示例所示。

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

如果具有现有的数组,则可以使用 Redim 语句重新定义其大小。 您可以指定 Redim 语句保留存储在数组中的值,或者指定它创建新的空数组。 下面的示例演示使用 Redim 语句修改现有数组的大小的不同方式。

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

有关详细信息,请参阅 ReDim 语句 (Visual Basic)

声明数组

使用 Dim 语句声明数组变量的方法与声明任何其他变量的方法一样。 在类型或变量名后面加上一对或多对圆括号,即指示该类型或变量将存储数组而不是标量(包含单个值的变量)。

声明数组后,您可以使用 ReDim 语句 (Visual Basic) 来定义数组的大小。

以下示例通过在类型后添加一对圆括号来声明一维数组变量。 该示例还通过使用 ReDim 语句 (Visual Basic) 指定数组的维数。

' Declare a one-dimensional array. 
Dim cargoWeights As Double()

' Dimension the array. 
ReDim cargoWeights(15)

以下示例通过在类型后面添加一对圆括号,并将圆括号内的各维度之间用逗号分隔,来声明多维数组变量。 该示例还通过使用 ReDim 语句 (Visual Basic) 指定数组的维数。

' Declare a multidimensional array. 
Dim atmospherePressures As Short(,,,)

' Dimension the array. 
ReDim atmospherePressures(1, 2, 3, 4)

若要声明交错数组变量,请在变量名后面为每个嵌套数组级添加圆括号对。

Dim inquiriesByYearMonthDay()()() As Byte

前面的示例只声明了数组变量,但没有为它们分配数组。 您仍必须创建数组,对该数组进行初始化,并将它分配给变量。

在数组中存储值

使用 Integer 类型的索引,可以访问数组中的每个位置。 通过使用括在圆括号内的索引来引用每个数组位置,可以在数组中存储和检索值。 多维数组的索引由逗号(,)分隔。 您需要每个数组尺寸的一个索引。 下面的示例是一些在数组中存储值的语句。

Dim i = 4
Dim j = 2

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

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

下面的示例演示了一些从数组中获取值的语句。

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

用初始值填充数组

通过使用数组文本,您可以创建包含一组初始值的数组。 数组文本由括在大括号 ({}) 内的一组逗号分隔值组成。

使用数组文本创建数组时,可以提供数组类型或使用类型推理确定数组类型。 以下代码演示了这两种方法。

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

使用类型推理时,数组的类型由为数组文本提供的值列表中的主导类型确定。 “主导类型”是数组文本中所有其他类型都可以扩大到的唯一类型。 如果无法确定此唯一类型,则主导类型是数组中所有其他类型都可以收缩到的唯一类型。 如果这两种唯一类型都无法确定,则主导类型是 Object。 例如,如果为数组文本提供的值列表包含 Integer、Long 和 Double 类型的值,则得到的数组属于 Double 类型。 Integer 和 Long 都仅扩大到 Double。 因此,Double 是主导类型。 有关详细信息,请参阅 扩大转换和收缩转换 (Visual Basic)。 这些推理规则适用于为数组(在类成员中定义的局部变量)推断的类型。 虽然在创建类级变量时可以使用数组文本,但是不能在类级使用类型推理。 因此,在类级指定的数组文本将为数组文本提供的值推断为类型 Object。

在使用数组文本创建的数组中,可以显式指定元素的类型。 在这种情况下,数组文本中的值必须扩大到数组的元素类型。 下面的代码示例从整数列表创建一个 Double 类型的数组。

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

嵌套的数组文本

使用嵌套的数组文本,可以创建多维数组。 嵌套的数组文本必须具有与所得数组一致的维度和维数(或“秩”)。 下面的代码示例使用数组文本创建一个二维整数数组。

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

在前面的示例中,如果嵌套的数组文本中的元素数不匹配,则会出现错误。 如果将数组变量显式声明为非二维,则也会出现错误。

备注

通过将内部数组文本括在圆括号内,可以在提供不同维度的数组文本时避免错误。括号强制计算数组文本表达式,并将结果值用于外部数组文本,如以下代码所示。

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

使用嵌套的数组文本创建多维数组时,可以使用类型推理。 使用类型推理时,推断出的类型是某嵌套级别的所有数组文本中所有值的主导类型。 下面的代码示例从 Integer 和 Double 类型的值创建一个 Double 类型的二维数组。

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

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

通过数组迭代

当您通过数组循环访问时,您从最低索引到最高索引访问数组中的每个元素。

以下示例通过使用 For...Next 语句 (Visual Basic) 重复一维数组。 GetUpperBound 方法返回索引可具有的最大值。 最小索引值始终为 0。

Dim numbers = {10, 20, 30}

For index = 0 To numbers.GetUpperBound(0)
    Debug.WriteLine(numbers(index))
Next 
' Output: 
'  10 
'  20 
'  30

以下示例通过使用 For...Next 语句重复多维数组。 GetUpperBound 方法具有指定维度的参数。 GetUpperBound(0) 返回第一个维的较大索引值,而 GetUpperBound(1) 返回第二个维的较大索引值。

Dim numbers = {{1, 2}, {3, 4}, {5, 6}}

For index0 = 0 To numbers.GetUpperBound(0)
    For index1 = 0 To numbers.GetUpperBound(1)
        Debug.Write(numbers(index0, index1).ToString & " ")
    Next
    Debug.WriteLine("")
Next 
' Output  
'  1 2  
'  3 4  
'  5 6

以下示例通过使用 For Each...Next 语句 (Visual Basic) 重复一维数组。

Dim numbers = {10, 20, 30}

For Each number In numbers
    Debug.WriteLine(number)
Next 
' Output: 
'  10 
'  20 
'  30

以下示例通过使用 For Each...Next 语句重复多维数组。 但是,如前面的示例所示,如果使用嵌套的 For…Next 语句,而非 For Each…Next 语句,将更易控制多维数组的元素。

Dim numbers = {{1, 2}, {3, 4}, {5, 6}}

For Each number In numbers
    Debug.WriteLine(number)
Next 
' Output: 
'  1 
'  2 
'  3 
'  4 
'  5 
'  6

作为返回值和参数的数组

若要从 Function 过程返回数组,请指定数组数据类型和维度数作为 Function 语句 (Visual Basic) 的返回类型。 在函数中,声明一个具有相同的类型和维的数量的局部数组变量。 在 Return 语句 (Visual Basic) 中,包含不带括号的本地数组变量。

若要将某个数组指定为一个 Sub 或 Function 过程的参数,则将该参数定义为带有指定数据类型和维数的数组。 在对过程的调用,发送数据类型和维数相同的数组变量。

在下面的示例中,GetNumbers 函数返回一个 Integer()。 此数组类型是一维数组类型 Integer。 ShowNumbers 程序接受 Integer() 参数。

Public Sub Process()
    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)
        Debug.WriteLine(numbers(index) & " ")
    Next 
End Sub 

' Output: 
'   10 
'   20 
'   30

在下面的示例中,GetNumbersMultiDim 函数返回一个 Integer(,)。 此数组类型是二维数组类型 Integer。ShowNumbersMultiDim 程序接受 Integer(,) 参数。

Public Sub ProcessMultidim()
    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)
            Debug.Write(numbers(index0, index1).ToString & " ")
        Next
        Debug.WriteLine("")
    Next 
End Sub 

' Output   
'  1 2   
'  3 4   
'  5 6

交错数组

包含其他数组的数组称为数组的数组或交错数组。 交错数组和交错数组中的每个元素都可以具有一个或多个维度。 有时,应用程序中的数据结构是两维的但不是矩形。

以下示例包含一个月份的数组,其每个元素又是天数的数组。 由于不同的月份有不同的天数,所以元素不能构成一个矩形的两维数组。 因此,可以使用交错数组而不是多维数组。

' Declare the jagged array. 
' The New clause sets the array variable to a 12-element 
' array. Each element is an array of Double elements. 
Dim sales()() As Double = New Double(11)() {}

' Set each element of the sales array to a Double 
' array of the appropriate size. 
For month As Integer = 0 To 11
    Dim days As Integer =
        DateTime.DaysInMonth(Year(Now), month + 1)
    sales(month) = New Double(days - 1) {}
Next month

' Store values in each element. 
For month As Integer = 0 To 11
    Dim upper = sales(month).GetUpperBound(0)
    For day = 0 To upper
        sales(month)(day) = (month * 100) + day
    Next 
Next

零长度数组

不含任何元素的数组也称为零长度数组。 存储零长度数组的变量不具有 Nothing 值。 若要创建没有元素的数组,请将数组的其中一个维度声明为 -1,如下面的示例所示。

Dim twoDimensionalStrings(-1, 3) As String

下列情况下可能需要创建一个零长度数组:

  • 如果不希望出现 NullReferenceException 异常,您的代码必须访问 Array 类的成员(例如 LengthRank)或调用像 UBound 这样的 Visual Basic 函数。

  • 您希望简化代码,不必将 Nothing 作为特例进行检查。

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

数组大小

数组的大小是数组的所有维度的长度乘积。 它表示数组中当前包含的元素的总数。

下面的示例声明一个三维数组:

Dim prices(3, 4, 5) As Long

变量 prices 中数组的总大小是 (3 + 1) x (4 + 1) x (5 + 1) = 120。

使用 Length 属性,可以查找数组的大小。 使用 GetLength 方法,可以查找多维数组中每个维度的长度。

通过为数组变量分配新的数组对象,或者通过使用 ReDim 语句,可以调整数组变量的大小。

处理数组大小时有几件事情需要注意。

维度长度

每个维度的索引从 0 开始,这意味着索引范围为从 0 到它的上限。 因此,给定维度的长度比该维度的声明上限大 1。

长度限制

数组的每个维度的长度最大为 Integer 数据类型的最大值 (2 ^ 31) - 1。 但是,数组的总大小还受系统可用内存的限制。 如果您尝试初始化超出可用 RAM 量的数组,公共语言运行时将引发 OutOfMemoryException 异常。

大小和元素大小

数组的大小与它的元素的数据类型无关。 大小始终表示元素的总数,而不是元素所占用的存储字节数。

内存消耗

对数组在内存中的存储方式做任何假定都是不安全的。 不同数据宽度的平台上的存储各不相同,因此同一个数组在 64 位系统中占用的内存比在 32 位系统中多。 根据初始化数组时系统配置的不同,公共语言运行时 (CLR) 可以分配存储来尽可能紧密地压缩元素,或者在自然的硬件边界上完全对齐元素。 另外,数组的控制信息也需要存储开销,而这类开销会随每个增加的维度而增加。

数组类型和其他类型

每个数组都具有数据类型,但与其元素的数据类型不同。 没有一种可用于所有数组的数据类型。 相反,数组的数据类型由数组的维数(或“秩”)和数组中元素的数据类型确定。 只有在两个数组变量具有相同的秩并且它们的元素具有相同的数据类型时,才能将它们看成属于同一数据类型。 数组中维度的长度不会影响数组数据类型。

每个数组从 Array 类继承,您可以将变量声明为 Array 类型,但不能创建 Array 类型的数组。 此外,ReDim 语句 (Visual Basic) 不能处理声明为 Array 类型的变量。 由于这些原因以及类型安全考虑,建议将每个数组声明为特定的类型,例如前面示例中的 Integer。

可以通过几种方法确定数组或其元素的数据类型。

  • 可以对变量调用 Object.GetType 方法,从而得到包含该变量的运行时类型的 Type 对象。 Type 对象在其属性和方法中保存了大量信息。

  • 可以将变量传递给 TypeName 函数,从而得到包含运行时类型的名称的 String。

  • 可以将变量传递给 VarType 函数,从而得到表示变量的类型分类的 VariantType 值。

下面的示例调用 TypeName 函数来确定数组的类型和数组中元素的类型。 数组类型是 Integer(,),而数组中元素的类型是 Integer。

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

使用集合替代数组

数组对于创建和处理固定数量的强类型对象最有用。 集合提供一种更灵活的处理对象组的方法。 与数组不同,处理的对象组可根据程序更改的需要动态地增长和收缩。

如果需要更改数组的大小,必须使用 ReDim 语句 (Visual Basic)。 当您这样做时,Visual Basic 会创建一个新数组并释放以前的数组以便处置。 这需要一定的执行时间。 因此,如果您处理的项数经常更改,或者您无法预测所需的最大项数,则可以使用集合来获得更好的性能。

对于某些集合,您可以为放入该集合的任何对象分配一个“键”,以便使用该键快速检索对象。

如果集合包含单一数据类型的元素,可使用 System.Collections.Generic 命名空间中的一个类。 “泛型”集合强制“类型安全”,因此无法向该集合中添加任何其他数据类型。 从泛型集合中检索元素时,不必确定元素的数据类型或转换它。

有关集合的更多信息,请参见 集合(C# 和 Visual Basic)

示例

下面的示例使用 .NET Framework 泛型类 List 来创建 Customer 对象的列表集合。

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

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

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

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

CustomerFile 集合的声明指定了它只能包含 Customer 类型的元素。 它还提供 200 个元素的初始容量。 过程 AddNewCustomer 检查新元素的有效性,然后将新元素添加到集合中。 过程 PrintCustomers 使用 For Each 循环来遍历集合并显示集合的元素。

相关主题

术语

定义

Visual Basic 中的数组维数

解释数组中的秩和维度。

如何:在 Visual Basic 中初始化数组变量

描述如何用初始值填充数组。

如何:在 Visual Basic 中对数组进行排序

论述如何按字母顺序对数组的各个元素进行排序。

如何:将一个数组赋给另一个数组 (Visual Basic)

论述用于将数组赋给另一个数组变量的规则和步骤。

数组疑难解答 (Visual Basic)

讨论在使用数组时出现的一些常见问题。

请参见

参考

Dim 语句 (Visual Basic)

ReDim 语句 (Visual Basic)

Array