VB6 передается по значению и проходит по ссылке
Я изо всех сил пытаюсь понять, передать по значению и передать по ссылке в VB6. Я полностью понимаю эти концепции в объектно-ориентированных языках программирования, таких как .NET и Java (я понимаю, что Java не имеет ссылки). Посмотрите на код ниже:
Private Sub Form_Load()
Dim Test As Integer
Test = 1
TestFunction Test 'line 5
MsgBox (Test)
End Sub
Private Sub TestFunction(ByVal i As Integer)
i = i + 1
End Sub
Когда я ставлю скобки вокруг Test в строке 5, в окне сообщения выводится 1, как я и ожидал. Теперь взгляните на код ниже:
Private Sub Form_Load()
Dim Test As Integer
Test = 1
TestFunction Test 'line 5
MsgBox Test
End Sub
Private Sub TestFunction(ByRef i As Integer)
i = i + 1
End Sub
Окно сообщения печатает 2, как я и ожидал. Однако, если вы добавите скобки в строку 5, в окне сообщения будет напечатано 1, чего я не ожидал. Похоже, что вызывающая функция может передаваться по значению, даже если переменная, определенная в вызываемой функции, является ByRef. Похоже, что это не так, т.е. если вызываемая функция имеет сигнатуру с переменной, определенной как ByVal, то она всегда будет ByVal (даже если в вызывающей функции нет скобок вокруг переменной). Что стоит за этим в VB6? Я понимаю, что это основной вопрос в VB6, но он смутил меня. Я прочитал документацию MSDN и понял, что это все правда, однако он не объясняет причины этого.
Ответы
Ответ 1
Это классическая игра в VB6. Это объяснено в руководстве VB6. В этом коде ниже VB6 рассматривает аргумент как выражение (Test), а не ссылку на переменную
TestFunction (Test)
Чтобы передать ссылку на переменную, опустите скобки или используйте устаревший Call
statement (для чего требуются скобки)
TestFunction Test
Call TestFunction(Test)
VB6 позволяет передавать выражения в аргументы ByRef
, даже если метод их изменяет. Например, вы можете написать
TestFunction (Test + 2)
Компилятор создает временную копию и передает ее по ссылке. VB.Net использует скобки аналогичным образом.
Вы также можете получить компилятор для создания временных копий, если TestFunction принимает два аргумента, например:
TestFunction (one), (two)
И вы можете получить временные копии даже при Call
, если вы удвоите свои скобки, добавив лишнюю лишнюю пару:
Call TestFunction((Test))
Ответ 2
Включение любого выражения в круглые скобки приводит к тому, что выражение сначала оценивается, прежде чем делать что-либо еще, даже если это выражение является только одной переменной. В вашем случае результат этого выражения затем передается в качестве аргумента.
Итак, вы фактически передаете аргумент по ссылке. Но аргумент, который вы передаете, является результатом выражения, а не исходной переменной. Вот почему исходная переменная не обновляется.