ByVal (Visual Basic)
Указывает, что аргумент передается по значению, поэтому вызываемая процедура или свойство не может изменить значение переменной, лежащей в основе аргумента в вызывающем коде. Если модификатор не указан, по умолчанию используется ByVal.
Так как используется по умолчанию, не нужно явно указывать ByVal ключевое слово в сигнатурах методов. Он, как правило, создает шумный код и часто приводит к тому, что ключевое слово не по умолчанию ByRef игнорируются.
Комментарии
Модификатор ByVal можно использовать в следующих контекстах:
Пример
В следующем примере демонстрируется использование механизма передачи ByVal параметров с аргументом ссылочного типа. В примере аргументом является c1 экземпляр класса Class1 . ByVal запрещает коду в процедурах изменять базовое значение ссылочного аргумента , c1 но не защищает доступные поля и свойства c1 .
Module Module1 Sub Main() ' Declare an instance of the class and assign a value to its field. Dim c1 As New Class1() c1.Field = 5 Console.WriteLine(c1.Field) ' Output: 5 ' ByVal does not prevent changing the value of a field or property. ChangeFieldValue(c1) Console.WriteLine(c1.Field) ' Output: 500 ' ByVal does prevent changing the value of c1 itself. ChangeClassReference(c1) Console.WriteLine(c1.Field) ' Output: 500 Console.ReadKey() End Sub Public Sub ChangeFieldValue(ByVal cls As Class1) cls.Field = 500 End Sub Public Sub ChangeClassReference(ByVal cls As Class1) cls = New Class1() cls.Field = 1000 End Sub Public Class Class1 Public Field As Integer End Class End Module
См. также раздел
- Удалить ByVal (правило стиля IDE0081)
- Ключевые слова
- Передача аргументов по значению и по ссылке
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Оператор Function
Объявляет название, аргументы и код, которые составляют основной текст процедурыFunction.
Синтаксис
[Public | Private | Friend] [ Static ] Functionname [ ( arglist ) ] [ Astype ]
[ операторы ]
[ name=expression ]
[ Выход из Function ]
[ операторы ]
[ name=expression ]
End Function
Синтаксис оператора Function содержит такие части:
| Part | Описание |
|---|---|
| Public | Необязательный параметр. Указывает на то, что процедура Function доступна для всех других процедур во всех модулях. При использовании в модуле, который содержит Option Private, процедура недоступна вне проекта. |
| Private | Необязательный параметр. Указывает на то, что процедура Function доступна только для других процедур в том модуле, в котором была объявлена. |
| Friend | Необязательный параметр. Используется только в модуле класса. Указывает на то, что процедура Function видима повсюду в проекте, но невидима для контроллера экземпляра объекта. |
| Static | Необязательный параметр. Указывает на то, что локальные переменные процедуры Function сохраняются между вызовами. Атрибут Static не влияет на переменные, которые были объявлены вне Function, даже если они используются в процедуре. |
| name | Обязательно. Название Function; соответствует стандарту соглашений об именовании переменных. |
| arglist | Необязательный параметр. Список переменных, представляющих аргументы, которые передаются в процедуру Function при вызове. В качестве разделителя переменных используется запятая. |
| type | Необязательный параметр. Тип данных значения, возвращаемого процедурой Function; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal (в настоящее время не поддерживается), Date, String (кроме фиксированной длины), Object, Variant или любым пользовательским типом. |
| Операторы | Необязательный параметр. Любая группа операторов, которая будет выполняться в процедуре Function. |
| выражение | Необязательный параметр. Возвращаемое значение Function. |
Аргумент arglist имеет следующий синтаксис и элементы:
[ Необязательный ] [ ByVal | ByRef ] [ ParamArray ] varname [ ( ) ] [ Кактип ] [ =defaultvalue ]
| Part | Описание |
|---|---|
| Необязательное | Необязательный параметр. Указывает, что аргумент не является обязательным. Если он используется, все последующие аргументы в arglist тоже должны быть необязательными и объявляться с использованием ключевого слова Optional. Optional не может использоваться для каких-либо аргументов, если используется ParamArray. |
| ByVal | Необязательный параметр. Указывает, что аргумент передается значением. |
| ByRef | Необязательный параметр. Указывает, что аргумент передается по ссылке. ByRef является значением по умолчанию в Visual Basic. |
| ParamArray | Необязательный параметр. Используется как последний аргумент в arglist, чтобы указать, что последний аргумент является массивом Optional элементов Variant. Ключевое слово ParamArray позволяет предоставлять произвольное число аргументов. Не может использоваться с аргументами ByVal, ByRef или Optional. |
| varname | Обязательно. Имя переменной, представляющее аргумент; соответствует стандарту соглашений об именовании переменных. |
| type | Необязательный параметр. Тип данных аргумента, передаваемого процедуре; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Decimal (в настоящее время не поддерживается), Date, String (только переменная длина), Object, Variant или определенный тип объекта. Если параметр объявлен без ключевого слова Optional, можно также указать тип, определяемый пользователем. |
| defaultvalue | Необязательный параметр. Любая константа или константное выражение. Действительно только для параметров Optional. Если типом является Object, явным значением по умолчанию может быть только Nothing. |
Замечания
Если обратное не указано явно с помощью параметров Public, Private, или Friend, процедуры Function общедоступны по умолчанию.
Если Static не используется, значение локальных переменных не сохраняется между вызовами.
Ключевое слово Friend может использоваться только в модулях классов. Однако доступ к процедурам Friend может осуществляться в любом модуле проекта. Процедура Friend не отображается в библиотеке типов своего родительского класса; процедура Friend не может быть привязана позднее.
Процедуры Function могут быть рекурсивными, то есть они могут вызывать сами себя для выполнения поставленной задачи. Однако рекурсия может стать причиной переполнения стека. Ключевое слово Static обычно не используется с рекурсивными процедурами Function.
Весь выполняемый код должен быть в процедурах. Нельзя определить процедуру Function внутри другой процедуры Function, Sub, или Property.
Оператор Exit Function вызывает немедленный выход из процедуры Function. Выполнение программы продолжается с оператором, следующим за оператором, который вызвал процедуру Function. В любом месте процедуры Function может появится любое количество операторов Exit Function.
Как и Sub, Function является отдельной процедурой, которая может содержать аргументы, выполнять наборы операторов и изменять значения их аргументов. Однако в отличие от Sub, процедуру Function можно использовать справа от выражения, как и при использовании любой встроенной функции, например Sqr, Cos или Chr, если необходимо использовать значение, возвращенное функцией.
Процедура Function вызывается с помощью имени функции, за которым следует список аргументов в круглых скобках в выражении. Ознакомьтесь с информацией об операторе Call, чтобы подробнее узнать о вызове процедур Function.
Чтобы вернуть значение функции, присвойте значение названию функции. В любом месте процедуры может появится любое количество таких назначений. Если параметру name не присвоено значение, процедура вернет значение по умолчанию: числовая функция вернет 0, строковая функция вернет строку нулевой длины («»), а функция Variant вернет значение Empty. Функция, которая возвращает объектную ссылку, возвращает значение Nothing, если для параметра name не присвоено ни одной объектной ссылки (с помощью Set) в Function.
В следующем примере показано, как присвоить функции возвращаемое значение. В этом случае значение False присваивается названию, чтобы указать, что некоторые значения не были найдены.
Function BinarySearch(. . .) As Boolean '. . . ' Value not found. Return a value of False. If lower > upper Then BinarySearch = False Exit Function End If '. . . End Function
Переменные, которые используются в процедурах Function, делятся на две категории: те, которые явно объявлены в процедуре, и те, которые нет.
Переменные, которые явно объявлены в процедуре (с помощью оператора Dim или его эквивалента), всегда являются локальными в процедуре. Переменные, которые используются, но не были явно объявлены в процедуре, также являются локальными, если они не были объявлены на более высоком уровне вне процедуры.
В процедуре может использоваться переменная, которая не была явно объявлена в процедуре, но если какой-либо элемент, который был определен на уровне модуля, имеет такое же название, может возникнуть конфликт. Если ваша процедура ссылается на необъявленную переменную, которая называется так же, как и другая процедура, константа или переменная, система посчитает, что ваша процедура ссылается на это название на уровне модуля. Следует явно объявлять переменные, чтобы избежать таких конфликтов. Используйте оператор Option Explicit для принудительного явного объявления переменных.
Visual Basic может менять порядок арифметических выражений для повышения внутренней эффективности. Избегайте использования процедуры Function в арифметических выражениях, если функция меняет значение переменных в одном выражении. Подробнее об арифметических операторах см. в разделе Операторы.
Пример
В этом примере оператор Function используется для объявления названия, аргументов и кода, которые составляют основной текст процедуры Function. В последнем примере используются фиксированные инициализированные аргументы Optional.
' The following user-defined function returns the square root of the ' argument passed to it. Function CalculateSquareRoot(NumberArg As Double) As Double If NumberArg < 0 Then ' Evaluate argument. Exit Function ' Exit to calling procedure. Else CalculateSquareRoot = Sqr(NumberArg) ' Return square root. End If End Function
Использование ключевых слов ParamArray позволяет функции принимать переменное число аргументов. В следующем определении он передается по значению.
Function CalcSum(ByVal FirstArg As Integer, ParamArray OtherArgs()) Dim ReturnValue ' If the function is invoked as follows: ReturnValue = CalcSum(4, 3, 2, 1) ' Local variables are assigned the following values: FirstArg = 4, ' OtherArgs(1) = 3, OtherArgs(2) = 2, and so on, assuming default ' lower bound for arrays = 1.
Необязательные аргументы могут иметь значения по умолчанию и типы, отличные от Variant.
' If a function's arguments are defined as follows: Function MyFunc(MyStr As String,Optional MyArg1 As _ Integer = 5,Optional MyArg2 = "Dolly") Dim RetVal ' The function can be invoked as follows: RetVal = MyFunc("Hello", 2, "World") ' All 3 arguments supplied. RetVal = MyFunc("Test", , 5) ' Second argument omitted. ' Arguments one and three using named-arguments. RetVal = MyFunc(MyStr:="Hello ", MyArg1:=7)
См. также
- Вызов процедур Sub и Function
- Общие сведения об именованных и необязательных аргументах
- Написание процедуры Function
- Типы данных
- Операторы
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
Обратная связь
Были ли сведения на этой странице полезными?
Эффективная передача аргументов
Все аргументы передаются в процедурыпо ссылке, если иное не указано явно. Передача аргументов по ссылке позволяет повысить эффективность, поскольку в этом случае для передачи аргумента в процедуру требуется одинаковое количество времени и памяти (4 байта) независимо от его типа данных.
Чтобы передать аргумент по значению, включите в объявление процедуры ключевое слово ByVal. Аргументы, передаваемые значением, потребляют от 2 до 16 байт в процедуре в зависимости от типа данных аргумента. Передача крупных типов данных занимает немного больше времени. В связи с этим не рекомендуется передавать по значению типы данных String и Variant.
При передаче аргумента по значению исходная переменная копируется. Изменения аргумента в рамках процедуры не отражаются на исходной переменной. Например:
Function Factorial (ByVal MyVar As Integer) ' Function declaration. MyVar = MyVar - 1 If MyVar = 0 Then Factorial = 1 Exit Function End If Factorial = Factorial(MyVar) * (MyVar + 1) End Function ' Call Factorial with a variable S. S = 5 Print Factorial(S) ' Displays 120 (the factorial of 5) Print S ' Displays 5.
Если в объявление функции не включено ключевое слово ByVal, предшествующий оператор Print отобразит значения 1 и 0. Это связано с тем, что MyVar затем будет ссылаться на переменную S , которая уменьшается на 1, пока не будет равно 0.
Так как ByVal создает копию аргумента, он позволяет передать вариант функции Factorial . Если процедура, в которой объявляется аргумент, имеет другой тип данных, передать вариант по ссылке нельзя.
См. также
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
Передача аргументов по значению и по ссылке (Visual Basic)
В Visual Basic можно передать аргумент в процедуру по значению или по ссылке. Это называется механизмом передачи и определяет, может ли процедура изменить программный элемент, лежащий в основе аргумента в вызывающем коде. Объявление процедуры определяет механизм передачи для каждого параметра, указывая ключевое слово ByVal или ByRef.
Различия
При передаче аргумента в процедуру следует учитывать несколько различий, которые взаимодействуют друг с другом:
- Является ли базовый программный элемент изменяемым или неизменяемым
- Указывает, является ли сам аргумент изменяемым или неизменяемым
- Указывает, передается ли аргумент по значению или по ссылке
- Тип данных аргумента является типом значения или ссылочным типом
Выбор механизма передачи
Для каждого аргумента следует тщательно выбирать механизм передачи.
- Защита. При выборе между двумя механизмами передачи наиболее важным критерием является возможность изменения вызывающих переменных. Преимущество передачи аргумента ByRef заключается в том, что процедура может возвращать значение в вызывающий код через этот аргумент. Преимущество передачи аргумента ByVal заключается в том, что он защищает переменную от изменения процедурой.
- Производительность. Хотя механизм передачи может повлиять на производительность кода, разница обычно незначительна. Одним из исключений из этого является переданный ByVal тип значения . В этом случае Visual Basic копирует все содержимое аргумента . Таким образом, для большого типа значения, такого как структура, может быть эффективнее передать его ByRef . Для ссылочных типов копируется только указатель на данные (четыре байта на 32-разрядных платформах и восемь байтов на 64-разрядных платформах). Поэтому можно передавать аргументы типа String или Object по значению без ущерба для производительности.
Определение механизма передачи
Объявление процедуры задает механизм передачи для каждого параметра. Вызывающий код не может переопределить ByVal механизм.
Если параметр объявлен с ByRef параметром , вызывающий код может принудительно принудить механизм к ByVal , заключив имя аргумента в круглые скобки в вызове . Дополнительные сведения см. в разделе Практическое руководство. Принудительная передача аргумента по значению.
По умолчанию в Visual Basic аргументы передаются по значению.
Время передачи аргумента по значению
- Если вызывающий элемент кода, лежащий в основе аргумента, является неизменяемым элементом, объявите соответствующий параметр ByVal. Никакой код не может изменить значение неизменяемого элемента.
- Если базовый элемент является изменяемым, но вы не хотите, чтобы процедура могла изменять свое значение, объявите параметр ByVal . Только вызывающий код может изменить значение изменяемого элемента, передаваемого по значению.
Время передачи аргумента по ссылке
- Если процедуре действительно необходимо изменить базовый элемент в вызывающем коде, объявите соответствующий параметр ByRef.
- Если правильное выполнение кода зависит от процедуры изменения базового элемента в вызывающем коде, объявите параметр ByRef . Если передать его по значению или вызывающий код переопределяет ByRef механизм передачи, заключив аргумент в круглые скобки, вызов процедуры может привести к непредвиденным результатам.
Пример
Описание
В следующем примере показано, когда следует передавать аргументы по значению, а когда передавать их по ссылке. В процедуре Calculate ByVal есть параметр и ByRef . Учитывая процентную ставку rate и сумму денег, задача процедуры состоит в том, debt чтобы вычислить новое значение для debt , которое является результатом применения процентной ставки к исходному значению debt . Так как debt является параметром ByRef , новое итоговое значение отражается в значении аргумента в вызывающем коде, соответствующему debt . Параметр rate является параметром, ByVal так как Calculate не должен изменять его значение.
Код
Module Module1 Sub Main() ' Two interest rates are declared, one a constant and one a ' variable. Const highRate As Double = 12.5 Dim lowRate = highRate * 0.6 Dim initialDebt = 4999.99 ' Make a copy of the original value of the debt. Dim debtWithInterest = initialDebt ' Calculate the total debt with the high interest rate applied. ' Argument highRate is a constant, which is appropriate for a ' ByVal parameter. Argument debtWithInterest must be a variable ' because the procedure will change its value to the calculated ' total with interest applied. Calculate(highRate, debtWithInterest) ' Format the result to represent currency, and display it. Dim debtString = Format(debtWithInterest, "C") Console.WriteLine("What I owe with high interest: " & debtString) ' Repeat the process with lowRate. Argument lowRate is not a ' constant, but the ByVal parameter protects it from accidental ' or intentional change by the procedure. ' Set debtWithInterest back to the original value. debtWithInterest = initialDebt Calculate(lowRate, debtWithInterest) debtString = Format(debtWithInterest, "C") Console.WriteLine("What I owe with low interest: " & debtString) End Sub ' Parameter rate is a ByVal parameter because the procedure should ' not change the value of the corresponding argument in the ' calling code. ' The calculated value of the debt parameter, however, should be ' reflected in the value of the corresponding argument in the ' calling code. Therefore, it must be declared ByRef. Sub Calculate(ByVal rate As Double, ByRef debt As Double) debt = debt + (debt * rate / 100) End Sub End Module
См. также раздел
- Процедуры
- Параметры и аргументы процедуры
- Практическое руководство. Передача аргументов в процедуру
- Практическое руководство. Изменение значения аргумента процедуры
- Практическое руководство. Защита аргумента процедуры от изменений значения
- Практическое руководство. Принудительная передача аргумента по значению
- Передача аргументов по позиции и по имени
- Типы значений и ссылочные типы
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.