VB.NET — функция не может изменить элемент массива

Я пытаюсь передать массив Sub, чтобы Sub мог изменить одно из значений массива.

Что-то вроде этого

Dim a As String = "STARTVALUE"

PopulateDataSet("Management", {a})

Public Sub PopulateDataSet(ByRef SomeRandomOtherVariable As String, ByRef ToBePopulatedVariables() As String)

    ToBePopulatedVariables(0) = "TheNewValue"

End Sub

Когда я запускаю код, я могу пройти через Sub и посмотреть, где ToBePopulatedVariables(0) — переменная A — имеет значение «STARTVALUE», а затем это значение изменяется на «TheNewValue».

Но когда управление возвращается вызывающему коду, значение a возвращается к «STARTVALUE».

Я пробовал все, что мог придумать. Любые идеи?


И @karl-anderson, и Nadeem_MK предполагают одно и то же.

Но

Dim a As String()
a(0) = "FirstVariable"
PopulateDataSet("Management", {a}) 

Возвращает «Ссылка на объект не указывает на экземпляр объекта».

При присвоении значения a(0)

Однако

Dim a As String() = {"FirstVariable"}

Бегает.

Но я все еще застрял с новым значением, которое не возвращается вызывающему коду. Я пытался сделать это с помощью ByVal и ByRef, но для массивов я не думаю, что это имеет значение. –


person TRH    schedule 25.11.2013    source источник
comment
Строки неизменяемы в .Net. Изменение значения первого элемента массива не меняет строку, на которую указывает a. Вместо этого он создает новую строку и заставляет первый элемент массива указывать на эту строку.   -  person Chris Dunaway    schedule 25.11.2013


Ответы (3)


В вашем последнем редактировании вы пытаетесь присвоить значение пустому массиву, поэтому он должен запускать исключение Object reference not set to an instance of an object, вам нужно указать границы массива при объявлении:

Dim a(0) As String
a(0) = "FirstValue"

Или вы можете сделать это так:

Dim a As String() = {"FirstValue"}

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

Public Class Form1
Private a As String()

Private Sub Test() ' Handles MyBase.Shown
    PopulateDataSet("Hello", a) : MsgBox(a.First)
    PopulateDataSet("World!", a, 5) : MsgBox(a(5))
    PopulateDataSet("I've said Hello World!", a, 10) : MsgBox(a.Last)
End Sub

Public Sub PopulateDataSet(ByVal NewValue As String,
                           ByRef Array As String(),
                           Optional ByVal ItemIndex As Integer = 0)

    If Array Is Nothing Then
        System.Array.Resize(Array, 1)
    ElseIf Not Array.Count > ItemIndex Then
        Do Until Array.Count > ItemIndex
            System.Array.Resize(Array, Array.Count + 1)
        Loop
    End If

    Array(ItemIndex) = NewValue

End Sub

End Class
person ElektroStudios    schedule 25.11.2013

Подумайте немного о том, что вы на самом деле здесь делаете:

Dim a As String = "STARTVALUE"

PopulateDataSet("Management", {a})

Вы создаете строку с именем a со значением STARTVALUE. Затем вы создаете новый массив ({a}), который содержит a. Вы вызываете PopulateDataSet, который заменяет первый элемент массива.

Почему вы не видите изменений?

Переменная a вообще не меняется, она по-прежнему STARTVALUE. У вас нет ссылки на созданный вами массив, поэтому вы не сможете наблюдать за изменением этого массива (он может быть даже уже удален сборщиком мусора).

Кроме того, PopulateDataSet ничего не возвращает, а просто меняет ToBePopulatedVariables. Также нет необходимости в ByRef.

Вы должны просто передать переменную, содержащую массив:

Dim a As String() = {"STARTVALUE"}
PopulateDataSet("Management", a)

поэтому вы можете получить доступ к a (который является массивом, а не строкой) после вызова PopulateDataSet.

person sloth    schedule 25.11.2013

Это вб.нет? Если это так, я думаю, что ваше объявление массива неверно.
Попробуйте это;

Dim a(0) As String
a(0) = "STARTVALUE"

PopulateDataSet("Management", a)

Public Sub PopulateDataSet(ByRef SomeRandomOtherVariable As String, ByRef ToBePopulatedVariables() As String)

    ToBePopulatedVariables(0) = "TheNewValue"

End Sub
person Nadeem_MK    schedule 25.11.2013
comment
Вы должны установить начальный размер для массива. В противном случае a(0) или любой другой элемент не существует. - person theGD; 25.11.2013