Массивы в Visual Basic

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

Массив позволяет ссылаться на эти связанные значения по одному имени и используя номер, называемый индексом или подиндексом, чтобы отличить элементы друг от друга. Отдельные значения, называются элементами массива. Они представляются непрерывной последовательностью от индекса 0 до наибольшего значения индекса.

В отличие от массива, переменная, содержащая одиночное значение, называется скалярной переменной.

Пример

В следующем примере объявляется переменная массива для хранения числа учеников в каждом классе школы.

Dim students(6) As Integer

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

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

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

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

Элементы массива "учеников"

Изображение массива, отображающее количество студентов

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

Для объявления переменной одномерного массива добавьте одну пару скобок после имени переменной.

Dim cargoWeights() As Double

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

Dim atmospherePressures(,,,) As Short

Для объявления переменной массива массивов добавьте столько пар скобок после имени переменной, сколько требуется уровней вложенных массивов.

Dim inquiriesByYearMonthDay()()() As Byte

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

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

Массив без элементов также называется массивом нулевой длины. Переменная, содержащая массив нулевой длины, не имеет значения Nothing. Чтобы создать массив без элементов, объявите одно из измерений массива равным -1, как показано в следующем примере.

Dim twoDimensionalStrings(-1, 3) As String

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

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

  • Требуется сделать соответствующий код проще, избежав необходимости проверки на значение Nothing как особый случай.

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

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

Массив можно создать двумя способами. Можно указать размер массива после его объявления или, так как массив является объектом, можно создать его с предложением Оператор New (Visual Basic) и присвоить его переменной массива. Можно выполнить это в рамках объявления массива или в последующей инструкции назначения, как показано в следующем примере.

cargoWeights = New Double() {}
atmospherePressures = New Short(,,,) {}
inquiriesByYearMonthDay = New Byte()()() {}

После выполнения этих операторов массивы имеют нулевую длину.

Примечание

Предложение New должно задавать имя типа, за которым должны следовать круглые скобки, после которых должны идти фигурные скобки ({}).Круглые скобки не представляют вызов конструктора массива.Они указывают, что тип объекта является типом массива.Можно указать начальные значения в фигурных скобках.Компилятор требует фигурные скобки, даже если значения не указаны.Таким образом, предложение New должно включать круглые и фигурные скобки, даже если и те и другие пусты.Если не указаны скобки, компилятор предполагает, что вызывается конструктор для заданного типа.

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

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 numbers = New Integer() {1, 2, 4, 8}
Dim doubles = {1.5, 2, 9.9, 18}

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

При создании многомерного массива с помощью вложенных литералов массива можно использовать вывод типа. При использовании вывода типа выводимый тип является главным типом для всех значений всех литералов массива какого-либо уровня вложенности. В следующем примере кода создается двухмерный массив типа Double из значений типа Integer и Double.

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

Дополнительные примеры см. в разделе Практическое руководство. Инициализация переменных массива в Visual Basic.

Сохранение значений в массиве

К любому местоположению в массиве можно получить доступ, используя индекс типа 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)

Для каждого измерения массива метод GetUpperBound возвращает максимально допустимое значение индекса. Наименьшее значение индекса всегда равно 0.

Размер массива

Размер массива является произведением длин всех его измерений. Он представляет собой общее число элементов, в данный момент содержащихся в массиве.

В следующем примере показано объявление трехмерного массива:

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

Размер и размер элемента

Размер массива не зависит от типа его элементов. Размер всегда представляет общее число элементов, а не число байтов, занимаемое массивом при хранении.

Затраты памяти

Небезопасно делать любые предположения относительно способа хранения массива в памяти. Хранение зависит от размерности данных платформы, так один и тот же массив может потреблять больше памяти на 64-разрядных системах, чем на 32-разрядных. В зависимости от конфигурации системы при инициализации массива общеязыковая среда выполнения (CLR) может указывать такие способы хранения, как упаковка элементов максимально близко друг к другу или выравнивание всех элементов по естественным аппаратным границам памяти. Кроме того массив нуждается в хранении служебной информации, и размер этой информации возрастает при каждом добавлении измерения.

Типы массива и другие типы

Типы данных

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

Каждый массив наследуется от класса System.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)))

Коллекции как альтернатива массивам

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

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

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

Специализированные коллекции

.NET Framework также предоставляет набор классов, интерфейсов и структур для общих и специальных коллекций. Пространства имен System.Collections и System.Collections.Specialized содержат определения и реализации, включающие словари, списки, очереди и стеки. Пространство имен System.Collections.Generic предоставляет многие из этих универсальных версий, которые принимают один или несколько аргументов.

Если в коллекции хранятся элементы только одного определенного типа данных, то универсальная коллекция имеет преимущество принудительного типа безопасности. Дополнительные сведения об универсальных элементах см. в разделе Универсальные типы в Visual Basic (Visual Basic).

Специализированные коллекции

.NET Framework также предоставляет набор классов, интерфейсов и структур для общих и специальных коллекций. Пространства имен System.Collections и System.Collections.Specialized содержат определения и реализации, включающие словари, списки, очереди и стеки. Пространство имен System.Collections.Generic предоставляет многие из этих универсальных версий, которые принимают один или несколько аргументов.

Если в коллекции хранятся элементы только одного определенного типа данных, то универсальная коллекция имеет преимущество принудительного типа безопасности. Дополнительные сведения об универсальных элементах см. в разделе Универсальные типы в Visual Basic (Visual Basic).

Пример

В следующем примере используется универсальный класс .NET Framework System.Collections.Generic.List<T> для создания коллекции-списка объектов 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)

Описание правил и действий для назначения массива другой переменной массива.

Практическое руководство. Замена массива на другой массив (Visual Basic)

Описание того, какие изменения возможны и как их выполнить.

Практическое руководство. Передача массива в процедуру или свойство (Visual Basic)

Объяснение того, как передать массив в качестве аргумента процедуры или свойства.

Практическое руководство. Возврат массива из процедуры или свойства (Visual Basic)

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

Устранение неполадок, связанных с массивами (Visual Basic)

Рассмотрение некоторых общих проблем, возникающих при работе с массивами.

См. также

Ссылки

Оператор Dim (Visual Basic)

Оператор ReDim (Visual Basic)

Array