Понятията
параметър и
аргумент често се смесват, но те имат различно значение. Нека да
илюстрираме с пример. Нека
имаме следната функция, която поема стринг от дадени числа:
Function RepeatString(ByVal
sInput
As String, ByVal
iCount As
Integer) As String
Dim i As Integer
For i = 1 To iCount
RepeatString = RepeatString & sInput
Next
End Function
Променливите
sInput и
iCount са
параметри на функцията. Всеки параметър има асоцииран тип данни.
Когато
викаме -
call тази функция, трябва да заместим параметрите с
променливи,
константи или
литерали, примерно:
s = RepeatString("
Anna",
4)
Eлементите, които подаваме на параметрите се наричат
аргументи.
Подаване на аргументи
Аргументите можем да подаваме към функцията по два начина:
по стойност - value или
референтно - by reference.
Декларацията
на
RepeatString съдържа ключовата дума ByVal в началото на всеки
параметър. Това специфицира, че
аргументът се подава по стойност към
тази функция. Подаването по стойност
- value означава, че стойност на
аргумента се подава към функцията. Това е когато
аргументът е променлива. Разгледайте кода:
Sub Inc(ByVal x As Integer)
x = x + 1
End Sub
Dim iVuzrast As Integer = 20
Inc(iVuzrast)
Msgbox(iVuzrast)
Финалният
ред:
Msgbox(iVuzrast)
показва 20. С други думи в реда:
Inc(iVuzrast)
няма
нищо. Причината е че
аргумента iVuzrast е подаден към процедурата Inc по стойност. Понеже само стойността (в този случай 20) е подадена, тази стойност се присвоява на
локалната променлива
x вътре в процедурата. Тази локална променлива нараства на 21, но когато процедурата свършва, се
разрушава. Променливата
iVuzrast не се подава към процедурата, така че нейната стойност не се променя.
От друга страна, ако модифицираме дефиницията на
процедурата Inc, замествайки ByVal с ByRef, нещата изглеждат по друг начин:
Sub Inc(ByRef x As Integer)
x = x + 1
End Sub
В
този случай към процедурата се подава
връзкакъм аргумента iVuzrast. Всъщност
процедурата оперира над променливата
iVuzrast и тя се променя на 21. Казано по друг начин, променливата представена с
параметъра x е всъщност подадената променлива
iVuzrast.
Във VB .NET, по подразбиране (default) аргументите се подават по
стойност.
Подаване на обекти - Passing Objects
Има
неуловима разлика при аргументите подадени към параметри на някой
обектен тип. Понеже
обектната променлива е
указател ; сочи връзката към (или адреса на) обекта.
Ако
подаваме
обектната променлива по стойност, тази стойност е всъщност адреса
на обекта. Така че
промените извършвани във виканата процедура са над самия
обект, а не върху негово копие. Изглежда като референтно
подаване, но не е. От друга страна, ако подадем
обектнатапроменлива референтно (
by reference), ние подаваме адреса на
променливата. С други думи, подаваме адреса на адреса на
обекта! В езици, които поддържат
указатели, това положение се нарича
двоенуказател- double pointer.
Нека
да илюстрираме с пример. Нека формата съдържа две текстови кутии:
TextBox1 с текст "
Purva" и
TextBox2 с текст "
Vtora":
Public Function GetText(ByVal txt As TextBox) As String
txt = Textbox2 ' Сменя референцията към
textbox
End Function
Sub Doit
Dim t As TextBox
t = TextBox1
GetText(t)
msgbox(t.Text) ' Дава TextBox1 когато ByVal,
TextBox2 когато
ByRef
End Sub
Ето
какво се случва, когато изпълним
Doit. Аргументът се подава към
GetText по стойност в този случай.
· На
променливата от тип
TextBox - t се присвоява адреса на
TextBox1, както е показано на Фиг.
55.
Фигура
55 . Присвояване на обектна връзка
·
GetText се извиква и се подава
t по стойност. След като
t съдържа адрес
mmmm от текстова кутия
TextBox1 (обект), локалната променлива
txt получава стойност
mmmm, както е показано на фигура 56.
Фигура
56 . Подаване на обект по стойност
· Единичният
ред код в
GetText се изпълнява, сега
txt сочи към
TextBox2, както е показано на фигура 57.
Фигура
57 . Присвояване на нова
обектна връзка
· Докато
се върне от
GetText,
t не е засегната, така че функция
MsgBox разпечатва стринга "
Purva."
Сега
да сменим ключова дума ByVal с ByRef в
GetText. Ето какво се случва:
· Променливата
на
TextBox -
t се присвоява на
TextBox1, както е показано на фигура 55.
·
GetText се извиква, подавайки
t референтно. Сега, txt e
t. Това е различно от
txt и
t съдържащи една и съща стойност, както в случая ByVal. Ситуацията е показана на фигура 58.
Фигура
58 . Подаване на обект референтно
· Единичният
ред код от
GetText се изпълнява, като
txt (и следователно
t) сочи
TextBox2, както е показано на фигура 59. В този случай адресът
pppp e на
TextBox2.
· След връщане от
GetText,
t сочи
TextBox2, така че функция
MsgBox показва "
Vtora."
Фигура
59 . Присвояване на нова обектна
връзка
Опционални аргументи
Във
VB .NET, параметрите могат да се декларират опционално с ключова дума Optional, както е показано в следния код:
Sub Calculate(Optional ByVal Switch As Boolean = False)
Всички
опционални параметри във VB .NET, трябва да се декларират със стойности
по подразбиране (default), които се подават към процедура,
ако викащата програма не поддържа този параметър.
Важат
следните правила за опционалните параметри:
· Всеки
опционален аргумент трябва да се специфицира със стойността по подразбиране, която трябва да е константен
израз (не променлива).
· Всеки
аргумент, следващ опционален аргумент, трябва да е също опционален.
Във
VB .NET, не съществува функция
IsMissing .
Ключова дума ParamArray
Ключова
дума ParamArray, съкратено от
Parameter Array, ни позволява да декларираме процедура с не специфициран брой
параметри. По тази
причина, всяко
извикване на процедурата може да използва различен брой параметри. Да
предположим, че искаме да дефинираме функция която намира средна стойност на
броя тестови точки, но броят на точките може да варира. Декларираме функцията както
следва:
Function GetAverage(ParamArray ByVal Scores( ) As
Single) As Single
Dim i As Integer
For i = 0 To UBound(Scores)
GetAverage = GetAverage + CSng(Scores(i))
Next
GetAverage = GetAverage / (UBound(Scores) + 1)
End Function
Сега
можем да извикаме функцията с вариращ брой аргументи:
Msgbox(GetAverage(1, 2, 3, 4, 5))
Msgbox(GetAverage(1, 2, 3))
Важат
следните правила за използването на ParamArray:
· Процедурата
може да има само един масив параметри, и той да е последния параметър на
процедурата.
· Масивът параметри трябва да се подава по стойност, и трябва изрично да се включи ByVal в дефиницията на процедурата.
· Масивът параметри трябва да e eдно-дименсионален. Ако типът не се декларира, се
счита за
Object.
· Масивът параметри автоматично е опционален. По подразбиране е празен едно-дименсионален
масив от параметри от тип масив.