ByRef и ByVal в VBScript

Я сталкиваюсь с чем-то странным в VBScript. При написании процедуры, в которой я хочу, чтобы параметр передавался по ссылке, способ вызова этой процедуры изменяет способ передачи этого параметра!

Вот пример:

Sub IncrementByRef(ByRef Value) Value = Value + 1 End Sub Sub IncrementByVal(ByVal Value) Value = Value + 1 End Sub Dim Num Num = 10 WScript.Echo "Num : " & Num IncrementByRef(Num) : WScript.Echo "IncrementByRef(Num) : " & Num IncrementByRef Num : WScript.Echo "IncrementByRef Num : " & Num IncrementByVal(Num) : WScript.Echo "IncrementByVal(Num) : " & Num IncrementByVal Num : WScript.Echo "IncrementByVal Num : " & Num 

И вот вывод:

 U:\>cscript //nologo byrefbyval.vbs Num : 10 IncrementByRef(Num) : 10 IncrementByRef Num : 11 IncrementByVal(Num) : 11 IncrementByVal Num : 11 U:\> 

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

 IncrementByRef Num 

но не так:

 IncrementByRef(Num) 

Мне это кажется странным. Есть ли способ убедиться, что параметры переданы ByRef, независимо от того, как вызывается процедура?

У Эрика Липперта есть отличная статья об использовании круглых скобок в VBScript: что вы имеете в виду «не может использовать круглые скобки?» Ваш пример иллюстрирует один из пунктов, которые он упоминает, а именно: включение аргумента ByRef в круглые скобки передает его как ByVal .

Короче говоря, круглые скобки в вызовах подпрограмм VBScript могут быть помещены не только вокруг списка аргументов, но и вокруг отдельных аргументов (в этом случае они принудительно ByVal ). И VBScript ожидает, что список аргументов будет заключен в круглые скобки, если используется ключевое слово Call . Поскольку вызов IncrementByRef(Num) не использует ключевое слово Call , VBScript рассматривает круглые скобки применительно к аргументу подпрограммы и, таким образом, передает его ByVal вместо ByRef .

Смущает, но так оно и работает.

Это особенность, а не ошибка:
http://msdn.microsoft.com/en-us/library/ee478101.aspx

Параметр ByRef передается по значению, если аргумент заключен в круглые скобки, а круглые скобки не применяются к списку аргументов.

Скобки применяются к списку аргументов, если выполняется одно из следующих условий:

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

  • В заявлении используется ключевое слово Call. (Ключевое слово Call может быть необязательно использовано для вызова подпрограммы или для вызова функции без назначения.)

Поэтому попробуйте использовать ключевое слово Call или вернуть значение.

Быть ясным. Круглые скобки имеют три разные цели.

  1. Используется для включения списка аргументов при определении или вызове процедуры
  2. Указание индексатора на массив.
  3. Как оператор в выражении.

Существует два способа вызова процедуры либо как оператор, либо как выражение.

Выражение: –

 x = func(y) 

Утверждение:-

 func y 

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

В вышесказанном, что сам сам представляет собой очень простой отступ. В этой точке мы могли бы использовать y + z . На самом деле мы можем использовать любое допустимое выражение в этой точке, включая тот, который использует оператор круглых скобок. Например:-

  x = (y) 

является допустимым выражением. Следовательно, когда вы это делаете:

  func(y) 

VBScript видит вызов func которому передается результат выражения (y) . Теперь даже если func определяет этот параметр как ByRef значение в y не будет затронуто, потому что y фактически не передавалось как параметр. То, что было принято, было результатом выражения (y) которое будет храниться где-то временным. Даже если это временное хранилище модифицировано func оно будет отброшено впоследствии и, следовательно, будет иметь такое же поведение, если бы параметр был отмечен как ByVal .

 IncrementByRef Num 

вызовы и приращения, используя ссылку на Num

 IncrementByRef (47 + 3) 

звонки и приращения с использованием ссылки на «50». Отбрасывается при выходе.

 IncrementByRef (Num) IncrementByRef (Num + 18)*5 IncrementByRef Cint("32") 

Все законны в Бейсике, как и в ФОРТРАНЕ. Запомнилось, что в одном раннем FORTRAN, проходящем через ref, вы могли изменить значение выражений типа

 5 

Это было довольно запутанно, что только очень маленькие, ранние составители FORTRAN имели такое поведение.

Я не уверен, что следую за вопросом или ответами, но я поделюсь этим.

Независимо от того, есть ли у вас подпрограмма функции, определение параметров, переданных в ByVal или ByRef будет определять, сохраняет ли значение параметра вне подпрограммы или вызова функции. Если у меня есть следующая функция:

 Function ThisFByRef(ByRef MyValue) End Function 

Все, что я делаю с параметром внутри функции (или подпрограммы), сохранит свое значение после завершения функции. ByVal и ByRef связаны с объемом подпрограммы или функции. Любой параметр, который передается ByVal , не сохранит изменения, которые происходят в вызываемой подпрограмме или функции. Альтернативно, любой параметр, который передается ByRef , сохранит значение, которое было изменено, в подпрограмму или функцию. Возврат значения может выполняться только с помощью функции, а не подпрограммы, и не влияет на значение переданного параметра, если параметр не принят ByRef и не изменяется в пределах функции. Например:

 Dim x Dim ThisFValue x = 0 ThisFValue = ThisFByRef(x) At this point the values would be: ThisFValue = 2 x = 1 x = 0 ThisFValue = ThisFByVal(x) At this point the values would be: ThisFValue = 2 x = 0 Function ThisFByRef(ByRef x) x = x + 1 ThisFByRef = x + 1 End Function Function ThisFByVal(ByVal x) x = x + 1 ThisFByVal = x + 1 End Function 

Это просто. Когда вы создаете функцию или sub, и вы можете вызвать их следующим образом:

Без возврата:

 myFunction "This is a reference" 

Для возвращаемого значения:

 myValue = myFunction ("This is a reference") 
  • Ошибка ASP 0177: 8007007e Ошибка сервера.CreateObject для COM-библиотеки DLL
  • Запрос Active Directory с помощью VBScript
  • Как установить повторяющееся расписание для xlsm-файла с помощью планировщика задач Windows
  • возвращать только цифры 0-9 из строки
  • Код для прокрутки всех файлов excel в указанной папке и вытаскивание данных из определенных ячеек
  • HTTP GET в VBS
  • Запуск Microsoft Access как запланированной задачи
  • Запуск командной строки молча с помощью VbScript и получение вывода?
  • Добавление кавычек в строку в VBScript
  • В VBScript мне нужен код для вычитания 1 из searchResult.Updates.Count, так что Count = 0 и WScript.Quit будут выполняться соответственно
  • Невозможно использовать круглые скобки при вызове Sub Error 800A0414 VBS
  • Interesting Posts

    Когда ADT устанавливает значение BuildConfig.DEBUG в false?

    Тип аксессуара UITableViewCell, проверенный на доступ и установка других непроверенных

    Быстрее ли иметь четыре раза 2 ГБ или два раза 4 ГБ ОЗУ с двухканальной материнской платой?

    android java lang runtimeexception не удается подключиться к службе камеры

    Windows 7: переместить системный раздел, необходимо обновить загрузочный раздел

    Может ли Android SDK работать с JDK 1.7?

    Итератор против

    Форматирование Word – необходимо выравнивать слева направо, справа налево в одной строке

    MySQL. Могу ли я ограничить максимально допустимое время выполнения запроса?

    Ошибка при установке .NET Framework 3.5 в Windows 10

    Какова цель неявного типа авторизации гранта в OAuth 2?

    Проверено или исключено исключение

    Мои Windows 10 pc получили очень медленно, хотя использование процессора и памяти в порядке. Что еще я могу сделать?

    Могу ли я заставить браузер автоматически переадресовывать на некоторые страницы?

    импортировать файл dat в R

    Давайте будем гением компьютера.