Поделиться через


Массивы в Visual Basic

Массив — это набор значений, которые называются элементами, логически связанными друг с другом. Например, массив может состоять из числа учащихся в каждом классе в средней школе; каждый элемент массива — это количество учащихся в одном классе. Аналогичным образом массив может состоять из оценок учащегося для класса; каждый элемент массива является одним классом.

Для хранения каждого из элементов данных можно использовать отдельные переменные. Например, если наше приложение анализирует оценки учащихся, мы можем использовать отдельную переменную для каждого учащегося, например englishGrade1, englishGrade2и т. д. Этот подход имеет три основных ограничения:

  • Мы должны знать во время разработки точно, сколько классов мы должны справиться.
  • Обработка большого количества классов быстро становится громоздким. Это, в свою очередь, делает приложение гораздо более вероятным для серьезных ошибок.
  • Трудно поддерживать. Каждый новый класс, который мы добавляем, требует, чтобы приложение было изменено, перекомпилировано и повторно развернуто.

Используя массив, можно ссылаться на эти связанные значения по одному имени и использовать число, которое называется индексом или подстроком , для идентификации отдельного элемента на основе его положения в массиве. Индексы массива варьируются от 0 до одного меньше общего числа элементов в массиве. При использовании синтаксиса Visual Basic для определения размера массива указывается самый высокий индекс, а не общее количество элементов в массиве. Вы можете работать с массивом как единицей, и возможность итерации его элементов освобождает вас от необходимости точно знать, сколько элементов он содержит во время разработки.

Несколько простых примеров перед подробным описанием:

' Declare a single-dimension array of 5 numbers.
Dim numbers(4) As Integer

' Declare a single-dimension array and set its 4 values.
Dim numbers = New Integer() {1, 2, 4, 8}

' Change the size of an existing array to 16 elements and retain the current values.
ReDim Preserve numbers(15)

' Redefine the size of an existing array and reset the values.
ReDim numbers(15)

' Declare a 6 x 6 multidimensional array.
Dim matrix(5, 5) As Double

' Declare a 4 x 3 multidimensional array and set array element values.
Dim matrix = New Integer(,) {{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}

' Declare a jagged array
Dim sales()() As Double = New Double(11)() {}

Элементы массива в простом массиве

Давайте создадим массив с именем students для хранения числа учащихся в каждом классе в средней школе. Индексы элементов находятся в диапазоне от 0 до 6. Использование этого массива проще, чем объявление семи переменных.

На следующем рисунке students показан массив. Для каждого элемента массива:

  • индекс элемента представляет школьный класс (индекс 0 представляет детский сад);

  • значение, содержащееся в элементе, представляет число учеников в этом классе.

Diagram showing an array of the numbers of students

В следующем примере содержится код Visual Basic, который создает и использует массив:


Module SimpleArray
   Public Sub Main()
      ' Declare an array with 7 elements.
      Dim students(6) As Integer

      ' Assign values to each element.
      students(0) = 23
      students(1) = 19
      students(2) = 21
      students(3) = 17
      students(4) = 19
      students(5) = 20
      students(6) = 22
      
      ' Display the value of each element.
      For ctr As Integer = 0 To 6
         Dim grade As String = If(ctr = 0, "kindergarten", $"grade {ctr}")
         Console.WriteLine($"Students in {grade}: {students(ctr)}")
      Next
   End Sub
End Module
' The example displays the following output:
'     Students in kindergarten: 23
'     Students in grade 1: 19
'     Students in grade 2: 21
'     Students in grade 3: 17
'     Students in grade 4: 19
'     Students in grade 5: 20
'     Students in grade 6: 22

В примере выполняется три действия:

  • Он объявляет массив с семью элементами students . Число 6 в объявлении массива указывает последний индекс в массиве; оно меньше числа элементов в массиве.
  • Он присваивает значения каждому элементу в массиве. Доступ к элементам массива выполняется с помощью имени массива и включает индекс отдельного элемента в скобках.
  • В нем перечисляется каждое значение массива. В примере используется инструкция для доступа к каждому For элементу массива по его номеру индекса.

Массив students в предыдущем примере является одномерным массивом, так как он использует один индекс. Массив, использующий несколько индексов или подстрок, называется многомерным. Дополнительные сведения см. в остальной части этой статьи и измерения массива в Visual Basic.

Создание массива

Размер массива можно определить несколькими способами.

  • Размер можно указать при объявлении массива:

    ' Declare an array with 10 elements.
    Dim cargoWeights(9) As Double               
    ' Declare a 24 x 2 array.
    Dim hourlyTemperatures(23, 1) As Integer
    ' Declare a jagged array with 31 elements.
    Dim januaryInquiries(30)() As String
    
  • Предложение можно использовать New для указания размера массива при его создании:

    ' Declare an array with 10 elements.
    Dim cargoWeights() As Double = New Double(9) {}
    ' Declare a 24 x 2 array.
    Dim hourlyTemperatures(,) As Integer = New Integer(23, 1) {}
    ' Declare a jagged array with 31 elements. 
    Dim januaryInquiries()() As String = New String(30)() {}
    

Если массив уже существует, его размер можно переопределить с помощью оператора ReDim . Можно указать, что инструкция ReDim хранит значения, которые находятся в массиве, или можно указать, что она создает пустой массив. В приведенном ниже примере показаны различные варианты использования оператора ReDim для изменения размера существующего массива.

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

Дополнительные сведения см. в инструкции ReDim.

Хранение значений в массиве

К любой позиции в массиве можно получить доступ, используя индекс типа Integer. Вы можете сохранять и извлекать значения массива, ссылаясь на позицию в нем с помощью индекса, заключенного в скобки. Индексы для многомерных массивов разделяются запятыми (,). Для каждого измерения массива требуется один индекс.

В следующем примере показаны некоторые инструкции, которые хранят и извлекают значения в массивах.


Module Example
   Public Sub Main()
      ' Create a 10-element integer array.
      Dim numbers(9) As Integer
      Dim value As Integer = 2
        
      ' Write values to it.
      For ctr As Integer = 0 To 9
         numbers(ctr) = value
         value *= 2
      Next
        
      ' Read and sum the array values.  
      Dim sum As Integer
      For ctr As Integer = 0 To 9
         sum += numbers(ctr)
      Next
      Console.WriteLine($"The sum of the values is {sum:N0}")
    End Sub
End Module
' The example displays the following output:
'     The sum of the values is 2,046

Заполнение массива литералом массива

Используя литерал массива, вы можете заполнить массив начальным набором значений одновременно с его созданием. Литерал массива состоит из списка разделенных запятыми значений, заключенных в фигурные скобки ({}).

При создании массива с помощью литерала массива можно либо указать тип массива, либо использовать определение типа для задания типа массива. В следующем примере показаны оба варианта.

' Array literals with explicit type definition.
Dim numbers = New Integer() {1, 2, 4, 8}
' Array literals with type inference.
Dim doubles = {1.5, 2, 9.9, 18}
' Array literals with explicit type definition.
Dim articles() As String = { "the", "a", "an" }

' Array literals with explicit widening type definition.
Dim values() As Double = { 1, 2, 3, 4, 5 }

При использовании вывода типов тип массива определяется доминирующим типом в списке литеральных значений. Доминирующий тип — это тип, к которому могут расшириться все остальные типы в массиве. Если такой уникальный тип нельзя определить, то главным будет тип, до которого можно сузить все другие типы массива. Если ни один из указанных уникальных типов нельзя определить, главным типом будет Object. Например, если список значений для литерала массива содержит значения типов Integer, Longи Double, результирующий массив будет иметь тип Double. Поскольку Integer и Long расширяется только до 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}}

Дополнительные примеры можно найти в статье How to: Initialize an Array Variable in Visual Basic (Практическое руководство. Инициализация переменной массива в Visual Basic).

Итерирование по массиву

При итерации по массиву вы обращаетесь к каждому элементу массива из самого низкого индекса к самому высокому или от самого низкого до самого низкого. Как правило, используйте один из следующих вариантов: For... Следующая инструкция или оператор For Each... Следующий оператор для итерации элементов массива. Если вы не знаете верхние границы массива, можно вызвать 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 Statementto итерации по одномерному массиву и двумерному массиву.


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 Statement . В следующем примере оператор используется 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[]

Кроме того, оператор ReDimArray не может работать с переменной, объявленной с типом . По этим причинам и для обеспечения безопасности типов рекомендуется объявлять каждый массив как конкретный тип.

Выяснить тип данных массива или его элементов можно несколькими способами.

  • Можно вызвать GetType метод переменной, чтобы получить Type объект, представляющий тип времени выполнения переменной. Объект Type содержит подробные сведения в своих свойствах и методах.
  • Вы можете передать переменную в функцию TypeName , чтобы получить String имя типа времени выполнения.

В следующем примере вызывается метод GetType и TypeName функция для определения типа массива. Тип массива : Byte(,). Обратите внимание, что свойство также указывает, Type.BaseType что базовый тип массива байтов является классом Array .


Module Example
   Public Sub Main()
      Dim bytes(9,9) As Byte
      Console.WriteLine($"Type of {nameof(bytes)} array: {bytes.GetType().Name}")
      Console.WriteLine($"Base class of {nameof(bytes)}: {bytes.GetType().BaseType.Name}")
      Console.WriteLine()
      Console.WriteLine($"Type of {nameof(bytes)} array: {TypeName(bytes)}")
   End Sub
End Module
' The example displays the following output:
' Type of bytes array: Byte[,]
' Base class of bytes: Array
' 
' Type of bytes array: Byte(,)


Массивы в качестве возвращаемых значений и параметров

Чтобы вернуть массив из процедуры Function, укажите тип данных массива и число измерений в качестве типа возвращаемого значения оператора Function. Внутри функции объявите локальную переменную массива с тем же числом измерений и типом данных. В оператор Return включите локальную переменную массива без скобок.

Чтобы задать массив в качестве параметра процедуры Sub или Function , определите параметр как массив с указанными типом данных и количеством измерений. В вызове процедуры передайте переменную массива с одинаковым типом данных и количеством измерений.

В следующем примере GetNumbers функция возвращает Integer()одномерный массив типа Integer. Процедура ShowNumbers принимает аргумент Integer() .


Module ReturnValuesAndParams
   Public Sub Main()
      Dim numbers As Integer() = GetNumbers()
      ShowNumbers(numbers)
   End Sub

   Private Function GetNumbers() As Integer()
      Dim numbers As Integer() = {10, 20, 30}
      Return numbers
   End Function

   Private Sub ShowNumbers(numbers As Integer())
      For index = 0 To numbers.GetUpperBound(0)
         Console.WriteLine($"{numbers(index)} ")
      Next
   End Sub
End Module
' The example displays the following output:
'   10
'   20
'   30
    

В следующем примере GetNumbersMultiDim функция возвращает Integer(,)двухмерный массив типа Integer. Процедура ShowNumbersMultiDim принимает аргумент Integer(,) .


Module Example
   Public Sub Main()
      Dim numbers As Integer(,) = GetNumbersMultidim()
      ShowNumbersMultidim(numbers)
   End Sub

   Private Function GetNumbersMultidim() As Integer(,)
      Dim numbers As Integer(,) = {{1, 2}, {3, 4}, {5, 6}}
      Return numbers
   End Function

   Private Sub ShowNumbersMultidim(numbers As Integer(,))
      For index0 = 0 To numbers.GetUpperBound(0)
         For index1 = 0 To numbers.GetUpperBound(1)
            Console.Write($"{numbers(index0, index1)} ")
         Next
         Console.WriteLine()
      Next
   End Sub
End Module
' The example displays the following output:
'     1 2
'     3 4
'     5 6

Массивы массивов

Иногда структура данных в приложении является двухмерной, но не прямоугольной. Например, можно использовать массив для хранения данных о высокой температуре каждого дня месяца. Первое измерение массива представляет месяц, но второе измерение представляет количество дней, а число дней в месяц не равномерным. Массив, который также называется массивом массивов, предназначен для таких сценариев. Массив с массивом, элементы которого также являются массивами. Массив массивов и каждый элемент в нем могут иметь одно или несколько измерений.

В следующем примере используется массив месяцев, каждый элемент которого является массивом дней. В этом примере используется массив, так как разные месяцы имеют разное количество дней. В примере показано, как создать массив, назначить ему значения, а также получить и отобразить его значения.

Imports System.Globalization

Module JaggedArray
   Public Sub Main()
      ' Declare the jagged array of 12 elements. Each element is an array of Double.
      Dim sales(11)() As Double
      ' Set each element of the sales array to a Double array of the appropriate size.
      For month As Integer = 0 To 11
         ' The number of days in the month determines the appropriate size.
         Dim daysInMonth As Integer =
            DateTime.DaysInMonth(Year(Now), month + 1)
         sales(month) = New Double(daysInMonth - 1) {}
      Next 

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

      ' Retrieve and display the array values.
      Dim monthNames = DateTimeFormatInfo.CurrentInfo.AbbreviatedMonthNames
      ' Display the month names.
      Console.Write("    ")
      For ctr = 0 To sales.GetUpperBound(0)
         Console.Write($" {monthNames(ctr)}   ")
      Next   
      Console.WriteLine()
      ' Display data for each day in each month.
      For dayInMonth = 0 To 30
         Console.Write($"{dayInMonth + 1,2}.  ")
         For monthNumber = 0 To sales.GetUpperBound(0)
            If dayInMonth > sales(monthNumber).GetUpperBound(0) Then 
               Console.Write("       ")
            Else
               Console.Write($"{sales(monthNumber)(dayInMonth),-5}  ")
            End If
         Next   
         Console.WriteLine()
      Next
   End Sub
End Module
' The example displays the following output:
'      Jan    Feb    Mar    Apr    May    Jun    Jul    Aug    Sep    Oct    Nov    Dec
'  1.  0      100    200    300    400    500    600    700    800    900    1000   1100
'  2.  1      101    201    301    401    501    601    701    801    901    1001   1101
'  3.  2      102    202    302    402    502    602    702    802    902    1002   1102
'  4.  3      103    203    303    403    503    603    703    803    903    1003   1103
'  5.  4      104    204    304    404    504    604    704    804    904    1004   1104
'  6.  5      105    205    305    405    505    605    705    805    905    1005   1105
'  7.  6      106    206    306    406    506    606    706    806    906    1006   1106
'  8.  7      107    207    307    407    507    607    707    807    907    1007   1107
'  9.  8      108    208    308    408    508    608    708    808    908    1008   1108
' 10.  9      109    209    309    409    509    609    709    809    909    1009   1109
' 11.  10     110    210    310    410    510    610    710    810    910    1010   1110
' 12.  11     111    211    311    411    511    611    711    811    911    1011   1111
' 13.  12     112    212    312    412    512    612    712    812    912    1012   1112
' 14.  13     113    213    313    413    513    613    713    813    913    1013   1113
' 15.  14     114    214    314    414    514    614    714    814    914    1014   1114
' 16.  15     115    215    315    415    515    615    715    815    915    1015   1115
' 17.  16     116    216    316    416    516    616    716    816    916    1016   1116
' 18.  17     117    217    317    417    517    617    717    817    917    1017   1117
' 19.  18     118    218    318    418    518    618    718    818    918    1018   1118
' 20.  19     119    219    319    419    519    619    719    819    919    1019   1119
' 21.  20     120    220    320    420    520    620    720    820    920    1020   1120
' 22.  21     121    221    321    421    521    621    721    821    921    1021   1121
' 23.  22     122    222    322    422    522    622    722    822    922    1022   1122
' 24.  23     123    223    323    423    523    623    723    823    923    1023   1123
' 25.  24     124    224    324    424    524    624    724    824    924    1024   1124
' 26.  25     125    225    325    425    525    625    725    825    925    1025   1125
' 27.  26     126    226    326    426    526    626    726    826    926    1026   1126
' 28.  27     127    227    327    427    527    627    727    827    927    1027   1127
' 29.  28            228    328    428    528    628    728    828    928    1028   1128
' 30.  29            229    329    429    529    629    729    829    929    1029   1129
' 31.  30            230           430           630    730           930           1130

В предыдущем примере значения присваиваются массиву с многоуровневым массивом For...Next на основе элемента с помощью цикла. Вы также можете назначать значения элементам массива с помощью вложенных литералы массива. Однако попытка использовать вложенные литералы массива (например, Dim valuesjagged = {{1, 2}, {2, 3, 4}}) создает ошибку компилятора BC30568. Чтобы исправить ошибку, заключите внутренние литералы массива в круглые скобки. Круглые скобки принудительно вычисляются выражение литерала массива, а результирующее значение используется с литералом внешнего массива, как показано в следующем примере.


Module Example
   Public Sub Main()
      Dim values1d = { 1, 2, 3 }
      Dim values2d = {{1, 2}, {2, 3}, {3, 4}}
      Dim valuesjagged = {({1, 2}), ({2, 3, 4})}
   End Sub
End Module

Массив с многомерным массивом, элементы которого содержат массивы. Таким образом, Array.Length свойство и Array.GetLength(0) метод возвращают количество элементов в одномерном массиве и Array.GetLength(1) создает исключение IndexOutOfRangeException , так как многомерный массив не является многомерным. Вы определяете количество элементов в каждой субарреи, извлекая значение свойства каждого подравля Array.Length . В следующем примере показано, как определить количество элементов в массиве с фрагментом.


Module Example
   Public Sub Main()
      Dim jagged = { ({1, 2}), ({2, 3, 4}), ({5, 6}), ({7, 8, 9, 10}) }
      Console.WriteLine($"The value of jagged.Length: {jagged.Length}.")
      Dim total = jagged.Length
      For ctr As Integer = 0 To jagged.GetUpperBound(0)
         Console.WriteLine($"Element {ctr + 1} has {jagged(ctr).Length} elements.") 
         total += jagged(ctr).Length 
      Next
      Console.WriteLine($"The total number of elements in the jagged array: {total}")
   End Sub
End Module
' The example displays the following output:
'     The value of jagged.Length: 4.
'     Element 1 has 2 elements.
'     Element 2 has 3 elements.
'     Element 3 has 2 elements.
'     Element 4 has 4 elements.
'     The total number of elements in the jagged array: 15

Массивы нулевой длины

Visual Basic различает неинициализированный массив (массив, значение которого равноNothing) и массив нулевой длины или пустой массив (массив без элементов).) Неинициализированный массив — это массив, который не был измерен или имел какие-либо значения, назначенные ему. Например:

Dim arr() As String

Массив нулевой длины объявляется с измерением -1. Например:

Dim arrZ(-1) As String

Массив нулевой длины может потребоваться создать в указанных ниже случаях.

  • Без риска NullReferenceException исключения код должен получить доступ к членам Array класса, например или Rankили вызвать функцию Visual Basic, например LengthUBound.

  • Вы хотите, чтобы код был простым, не проверяя Nothing его как особый случай.

  • Код взаимодействует с интерфейсом API, который требует передачи массива нулевой длины в одну или несколько процедур или возвращает массив нулевой длины из одной или нескольких процедур.

Разделение массива

В некоторых случаях может потребоваться разделить один массив на несколько массивов. Это включает определение точки или точек, в которых должен быть разделен массив, а затем плевать массив на два или более отдельных массивов.

Примечание

В этом разделе не рассматривается разделение одной строки на массив строк на основе некоторого разделителя. Сведения о разделении строки см. в описании String.Split метода.

Наиболее распространенными критериями разделения массива являются:

  • Количество элементов в массиве. Например, может потребоваться разделить массив из более чем указанного числа элементов на несколько примерно равных частей. Для этого можно использовать значение, возвращаемое методом или Array.GetLength методомArray.Length.

  • Значение элемента, которое служит разделителем, указывающим, где должен быть разделен массив. Чтобы найти определенное значение, вызовите 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 помощью инструкции, коллекции растут и сжимаются динамически по мере изменения потребностей приложения.

При повторном ReDim создании массива Visual Basic создает новый массив и освобождает предыдущий. Это занимает время выполнения. Таким образом, если количество элементов, с которыми вы часто работаете, или вы не можете спрогнозировать максимальное количество необходимых элементов, обычно вы получите более высокую производительность с помощью коллекции.

Некоторые коллекции допускают назначение ключа любому объекту, который добавляется в коллекцию, чтобы в дальнейшем можно было быстро извлечь связанный с ключом объект из коллекции.

Если коллекция содержит элементы только одного типа данных, можно использовать один из классов в пространстве имен System.Collections.Generic. Универсальная коллекция обеспечивает строгую типизацию, так что в нее нельзя добавить другие типы данных.

Более подробную информацию о коллекциях см. в статье Коллекции.

Термин Определение
Array Dimensions in Visual Basic Объяснение ранга и измерений в массиве.
How to: Initialize an Array Variable in Visual Basic (Практическое руководство. Инициализация переменной массива в Visual Basic) Описывается заполнение массивов начальными значениями.
How to: Sort An Array in Visual Basic (Практическое руководство. Сортировка массива в Visual Basic) Показано, как сортировать элементы массива в алфавитном порядке.
Практическое руководство. Присвоение одного массива другому Описываются правила и действия для присвоения массива другой переменной массива.
Устранение неполадок, связанных с массивами Рассматриваются некоторые общие проблемы, возникающие при работе с массивами.

См. также раздел