Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
(ebook) Visual Studio .NET Mastering Visual Basic.pdf
Скачиваний:
120
Добавлен:
17.08.2013
Размер:
15.38 Mб
Скачать

160 Chapter 4 WRITING AND USING PROCEDURES

Functions can be called from within expressions, as the following statement shows:

MsgBox(“40 degrees Celsius are “ & Fahrenheit(40).ToString & _ “ degrees Fahrenheit”)

Notice that the ToString method applies to the numeric value returned by the function, and you need not implement it as part of your function. All numeric types provide the ToString method, which converts the numeric value to a string.

Suppose the function CountWords() counts the number of words and the function CountChars() counts the number of characters in a string. The average length of a word could be calculated as follows:

Dim longString As String, avgLen As Double longString = TextBox1.Text

avgLen = CountChars(longString) / CountWords(longString)

The first executable statement gets the text of a TextBox control and assigns it to a variable, which is then used as an argument to the two functions. When the second statement executes, Visual Basic first calls the functions CountChars() and CountWords() with the specified arguments and then divides the results they return.

You can call functions in the same way that you call subroutines, but the result won’t be stored anywhere. For example, the function Convert() may convert the text in a textbox to uppercase and return the number of characters it converts. Normally, you’d call this function as follows:

nChars = Convert()

If you don’t care about the return value—you only want to update the text on a TextBox control— you would call the Convert() function with the following statement.

Convert()

VB6 VB.NET

The Call statement of VB6 has disappeared. Also, the parentheses around the argument list are mandatory, even if the subroutine or function doesn’t accept any arguments. You can no longer call a subroutine with a statement like

ConvertText myText

You must enclose the arguments in a pair of parentheses:

ConvertText(myText)

Arguments

Subroutines and functions aren’t entirely isolated from the rest of the application. Most procedures accept arguments from the calling program. Recall that an argument is a value you pass to the procedure and on which the procedure usually acts. This is how subroutines and functions communicate with the rest of the application.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

ARGUMENTS 161

Functions also accept arguments—in many cases, more than one. The function Min(), for instance, accepts two numbers and returns the smaller one:

Function Min(ByVal a As Single, ByVal b As Single) As Single

Min = IIf(a < b, a, b)

End Function

IIf() is a built-in function that evaluates the first argument, which is a logical expression. If the expression is True, the IIf() function returns the second argument. If the expression is False, the function returns the third argument.

To call this function use a few statements like the following:

Dim val1 As Single = 33.001 Dim val2 As Single = 33.0011 Dim smallerVal as Single smallerVal = Min(val1, val2)

Console.Write(“The smaller value is “ & smallerVal)

If you execute these statements (place them in a button’s Click event handler), you will see the following on the Output window:

The smaller value is 33.001

If you attempt to call the same function with two double values, as in a statement like the following:

Console.WriteLine(Min(3.33000000111, 3.33000000222))

you will see the value 3.33 in the Output window. The compiler converted the two values from Double to Single data type and returned one of them. Which one is it? It doesn’t make a difference, because when converted to Single, both values are the same.

Interesting things will happen if you attempt to use the Min() function with the Strict option turned on. Insert the statement Option Strict On at the very beginning of the file. First, the editor will underline the statement that implements the Min() function—the IIf() function. The IIf() function accepts two Object variables as arguments, and you can’t call it with Single or Double values. The Strict option prevents the compiler from converting numeric values to objects. To use the IIf() function with the Strict option, you must change its implementation as follows:

Function Min(ByVal a As Object, ByVal b As Object) As Object

Min = IIf(Val(a) < Val(b), a, b)

End Function

Argument-Passing Mechanisms

One of the most important issues in writing procedures is the mechanism used to pass arguments. The examples so far have used the default mechanism: passing arguments by value. The other mechanism is passing them by reference. Although most programmers use the default mechanism, it’s important to know the difference between the two mechanisms and when to use each.

Passing Arguments by Value

When you pass an argument by value, the procedure sees only a copy of the argument. Even if the procedure changes it, the changes aren’t permanent. The benefit of passing arguments by value is that

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

162 Chapter 4 WRITING AND USING PROCEDURES

the argument values are isolated from the procedure, and only the code segment in which they are declared can change their values. This is the default argument-passing mechanism in VB.NET.

To specify the arguments that will be passed by value, use the ByVal keyword in front of the argument’s name. If you omit the ByVal keyword, the editor will insert it automatically, since it’s the default option. To declare that the Degrees() function’s arguments are passed by value, use the ByVal keyword in the argument’s declaration as follows:

Function Degrees(ByVal Celsius as Single) As Single

Degrees = (9 / 5) * Celsius + 32

End Function

To see what the ByVal keyword does, add a line that changes the value of the argument in the function:

Function Degrees(ByVal Celsius as Single) As Single

Degrees = (9 / 5) * Celsius + 32

Celsius = 0

End Function

Now call the function as follows:

CTemp = InputBox(“Enter temperature in degrees Celsius”) MsgBox(CTemp.ToString & “ degrees Celsius are “ & Degrees((CTemp)) & _

“ degrees Fahrenheit”)

If the value entered in the InputBox is 32, the following message is displayed:

32 degrees Celsius are 89.6 degrees Fahrenheit

Replace the ByVal keyword with the ByRef keyword in the function’s definition and call the function as follows:

Celsius = 32.0

FTemp = Degrees(Celsius)

MsgBox(Celsius.ToString & “ degrees Celsius are “ & FTemp & _ “ degrees Fahrenheit”)

This time the program displays the following message:

0 degrees Celsius are 89.6 degrees Fahrenheit

When the Celsius argument was passed to the Degrees() function, its value was 32. But the function changed its value, and upon return it was 0. Because the argument was passed by reference, any changes made by the procedure affected the variable permanently. When the calling program attempted to use it, the variable had a different value than expected.

Note When you pass arguments to a procedure by reference, you’re actually passing the variable itself. Any changes made to the argument by the procedure will be permanent. When you pass arguments by value, the procedure gets a copy of the variable, which is discarded when the procedure ends. Any changes made to the argument by the procedure won’t affect the variable of the calling program.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

ARGUMENTS 163

Note When you pass an array as argument to a procedure, the array is always passed by reference—even if you specify the ByVal keyword. The reason for this is that it would take the machine some time to create a copy of the array. Since the copy of the array must also live in memory, passing too many arrays back and forth by value would deplete your system’s memory.

Passing Arguments by Reference

Passing arguments by reference gives the procedure access to the actual variable. The calling procedure passes the address of the variable in memory so that the procedure can change its value permanently. With VB6, this was the default argument-passing mechanism, but this is no longer the case.

Start a new Visual Basic project and enter the following function definition in the form’s code window:

Function Add(ByRef num1 As Integer, ByRef num2 As Integer) As Integer Add = num1 + num2

num1 = 0 num2 = 0 End Function

This simple function adds two numbers and then sets them to zero.

Next, place a Command button on the form and enter the following code in the button’s Click event:

Dim A As Integer, B As Integer

A = 10

B = 2

Dim Sum As Integer

Sum = Add(A, B)

Console.WriteLine(A)

Console.WriteLine(B)

Console.WriteLine(Sum)

This code displays the following results in the Output window:

0

0

12

The changes made to the function’s arguments take effect even after the function has ended. The values of the variables A and B have changed value permanently.

Now change the definition of the function by inserting the keyword ByVal before the names of the arguments, as follows:

Function Add(ByVal num1 As Integer, ByVal num2 As Integer) As Integer

With this change, Visual Basic passes copies of the arguments to the function. The rest of the program remains the same. Run the application, click the button, and the following values display in the Output window:

10

2

12

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

164 Chapter 4 WRITING AND USING PROCEDURES

The function has changed the values of the arguments, but these changes remain in effect only in the function. The variables A and B in the Button1_Click event handler haven’t been affected.

As you type the names of the arguments in the declaration of a subroutine or function, the editor inserts automatically the ByVal keyword if you omit it (unless, of course, you specify the ByRef keyword). In general, you pass arguments by reference only if the procedure has reason to change its value. If the values of the arguments are required later in the program, you run the risk of changing their values in the procedure.

Returning Multiple Values

If you want to write a function that returns more than a single result, you will most likely pass additional arguments by reference and set their values from within the function’s code. The following function calculates the basic statistics of a data set. The values of the data set are stored in an array, which is passed to the function by reference.

The Stats() function must return two values, the average and standard deviation of the data set. In a real-world application, a function like Stats() should calculate more statistics than this, but this is just an example to demonstrate how to return multiple values through the function’s arguments. Here’s the declaration of the Stats() function:

Function Stats(ByRef Data() As Double, ByRef Avg As Double, _

ByRef StDev As Double) As Integer

The function returns an integer, which is the number of values in the data set. The two important values calculated by the function are returned in the Avg and StDev arguments.

Function Stats(ByRef Data() As Double, ByRef Avg As Double, _ ByRef StDev As Double) As Integer

Dim i As Integer, sum As Double, sumSqr As Double, points As Integer points = Data.Length

For i = 0 To points - 1 sum = sum + Data(i)

sumSqr = sumSqr + Data(i) ^ 2 Next

Avg = sum / points

StDev = System.Math.Sqrt(sumSqr / points - Avg ^ 2) Return(points)

End Function

To call the Stats() function from within your code, set up an array of doubles and declare two variables that will hold the average and standard deviation of the data set:

Dim Values(100) As Double

‘ Statements to populate the data set Dim average, deviation As Double

Dim points As Integer

points = Stats(Values, average, deviation) Console.WriteLine points & “ values processed.” Console.WriteLine “The average is “ & average & “ and” Console.WriteLine “the standard deviation is “ & deviation

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com