An argument is a piece of data passed from the calling routine to a procedure.
Passing
Constant Literals
Private Sub
cmdTest_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdTest.Click
Call repeatChars ("+", 10)
Call repeatChars ("=", 15)
End Sub
Private Sub repeatChars (ByVal
character as String, ByVal count as Integer)
Dim lcv As Integer
For lcv = 1 to count
Console.Write(character)
Next lcv
Console.WriteLine()
End Sub
- The values supplied in the call must be of the types specified in the declaration: the
first argument must be of type String
and the second argument must be of type Integer.
- The types in the declaration and the definition must also agree, and there must be the
same number.
- The calling program supplies arguments to the procedure. The variables used within the
procedure to hold the argument values are called parameters.
- The declarator in the procedure definition specifies both the data types and the names
of the parameters:
- These parameter names are used in the procedure as if they were normal variables.
- When the procedure is called, its parameters are automatically initialized to the values
passed by the calling program.
Passing Variables
Variables can also be passed as arguments, as seen in the following code segment.
Dim characterIn As String
Dim count As Integer
characterIn = "@"
count = 24
Call repeatChars (characterIn, count)
Call-by-Value vs. Call-by-Reference
There are two ways to pass parameters to procedures: call-by-value and call-by-reference.
Call-by-value
- the default for argument passing.
- The procedure creates new variables to hold the values of the arguments.
The procedure gives these new variables the names and data types of the parameters
specified in the declarator: character of type
String and number of type
Integer. It initializes these parameters to the values passed, and they can then be accessed
like other variables by statements in the procedure body.
- passes a copy of the argument's value to the called routine, and that copy can be
manipulated without affecting the original value in the calling routine.
- This makes it possible to modify the values in the procedure without
affecting the original variables. This offers insurance that the procedure cannot harm the
original variable by using a copy of the original variable.
- An argument can be passed call-by-value either by using keyword
ByVal in the declaration or
by enclosing that argument in the call in parentheses, ( ). Placing
the argument in its own set of parentheses forces evaluation of it as an
expression.
- The parenthesis in the call and keyword
ByVal in the declaration can be used together or separately.
- Be sure all parameters in a function are passed ByVal.
________________
Call-by-reference
- provides a mechanism for returning more than one value from the procedure
back to the calling program.
- Passing arguments by reference passes a reference to the original
variable (in the calling program)
- allows the called procedure to directly access the caller's data, and to modify
that data if the called procedure so chooses.
- The primary advantage/drawback of passing by reference is that the
procedure can access the actual variables in the calling program.
- This is dangerous because the called procedure can alter the original parameter,
possibly resulting in hard-to-detect side effects.
________________
The following header declares two variables:
Private
Sub TestIt ( ByVal var1 As Long, ByRef var2 As Boolean )
TestIt receives var1 by value and var2 by reference.
TestIt could be rewritten as
Private Sub TestIt (
var1 As Long, ByRef var2 As
Boolean )
The call
Call
TestIt ( (passACopy), passOriginal )
passes passACopy by value and passOriginal by reference.
Passing Simple Data Types by Reference
Private Sub cmdTest_Click(ByVal
sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdTest.Click
Dim targetNumber As Single
Dim integerPortion As Single = 0
Dim fractionalPortion As Single = 0
targetNumber =
3.14159
Call
integerFraction (targetNumber, integerPortion, fractionalPortion)
Console.WriteLine("Integer portion is " &
integerPortion)
Console.WriteLine("Fractional portion is " & fractionalPortion)
End Sub
Private Sub integerFraction (ByVal number As
Single, _
integerPart As Single,
_
fractionalPart As Single)
integerPart = Int (number)
fractionalPart = number - integerPart
End Sub
Private Sub integerFraction (ByVal number As
Single, _
ByRef integerPart As Single, _
ByRef fractionalPart As Single)
integerPart = Int (number)
fractionalPart = number - integerPart
End Sub
The following program demonstrates call-by-value and call-by-reference.
The program contains three procedures that receive arguments call-by-value and two
procedures that receive an argument call-by-reference.
' ByRefTest.vb -- Demonstrates passing by reference.
Module modByRefTest
' squares three values ByVal and ByRef, displays
results
Sub Main()
Dim number1 As Integer = 2
Console.WriteLine("Passing a value-type argument
by value:")
Console.WriteLine("Before calling SquareByValue, "
& _
"number1 is {0}", number1)
SquareByValue(number1) ' passes number1 by value
Console.WriteLine("After returning from
SquareByValue, " & _
"number1 is {0}" & vbCrLf, number1)
Dim number2 As Integer = 2
Console.WriteLine("Passing a value-type argument"
& _
" by reference:")
Console.WriteLine("Before calling
SquareByReference, " & _
"number2 is {0}", number2)
SquareByReference(number2) ' passes number2 by
reference
Console.WriteLine("After returning from " & _
"SquareByReference, number2 is {0}" & vbCrLf,
number2)
Dim number3 As Integer = 2
Console.WriteLine("Passing a value-type argument"
& _
" by reference, but in parentheses:")
Console.WriteLine("Before calling
SquareByReference " & _
"using parentheses, number3 is {0}", number3)
SquareByReference((number3)) ' passes number3 by
value
Console.WriteLine("After returning from " & _
"SquareByReference, number3 is {0}", number3)
End Sub ' Main
' squares number by value (note ByVal keyword)
Sub SquareByValue(ByVal number As Integer)
Console.WriteLine("After entering SquareByValue, "
& _
"number is {0}", number)
number *= number
Console.WriteLine("Before exiting SquareByValue, "
& _
"number is {0}", number)
End Sub ' SquareByValue
' squares number by reference (note ByRef keyword)
Sub SquareByReference(ByRef number As Integer)
Console.WriteLine("After entering
SquareByReference" & _
", number is {0}", number)
number *= number
Console.WriteLine("Before exiting
SquareByReference" & _
", number is {0}", number)
End Sub ' SquareByReference
End Module ' modByRefTest
| |
Call-By-Value |
Call-By-Reference |
| Parameter Use |
Manipulate copy of data |
Manipulate original data |
| Keyword in heading |
ByVal |
ByRef |
| Keyword in call |
( ) |
|
| Default |
Yes |
No |
| Dangerous |
No |
Yes |
| Can "return" value |
No |
Yes |
Coercion
-
Another important feature of procedure definitions is the coercion of arguments, i.e., the forcing of arguments to the appropriate type to pass to a
procedure.
-
Widening conversions occur when a
type is converted to another type (usually one that can represent larger
values) without losing data. One example is the conversion of an Integer
to a Long or Decimal.
-
Narrowing conversions occur when
there is potential for data loss during conversion (usually to a type that
holds a smaller amount of data). One example is the conversion of a
Double to a Single or an Integer.
-
The Math class method Sqrt can be called with an
Integer argument even though the method is defined in the Math class to receive a
Double argument, and the method will still work correctly. The statement
Console.WriteLine( Math.sqrt( 4 ) );
correctly evaluates Math.sqrt( 4 ), and prints the value 2.
-
The method definition's parameter list causes the Integer value 4 to be converted
or promoted to the Double value 4.0 before the value is passed to Math.Sqrt.
-
In cases like this, argument values that do not correspond precisely to the parameter types in the method definition are converted to the proper type
through an implicit widening conversion before the method is called.
-
VB also performs narrowing
conversions on arguments passed to procedures. For example, if a textbox
contains the String value "4", the method call Math.Sqrt(txtNum.Text))
correctly evaluates to 2.
-
In some cases, these conversions can lead to compiler errors if the promotion rules are not followed. The promotion rules specify how types can be converted to other types without losing data.
-
In the Math.Sqrt example above, an Integer is automatically converted to a Double without changing its value. However, a
Double converted to an Integer truncates the fractional part of the Double value. Converting large integer types to small integer types (e.g., Long to Integer) may also result in changed values.
-
The promotion rules apply to expressions containing values of two or more data types; such expressions are also referred to as mixed-type expressions. The type of each value in a mixed-type expression is promoted to the ''highest'' type in the expression.
Converting values to lower types can result in incorrect values. Therefore you
can set an option, Option Strict to ON, so that in cases where information may be lost due to conversion the compiler requires the programmer to use a cast operator to force the conversion to occur.
To convert a Double to an Integer you can use
intNum = CInt(doubNum) or
intNum = Convert.ToInt32(doubNum)
These statements explicitly convert the value of doubNum to an Integer.
|