All logic statements in your code must appear within a procedure, whether in a subroutine, a function, or a property. Although there are thousands of prewritten procedures for you to choose from in the Framework libraries, you can also add your own.
Subroutines begin with a Sub declaration statement and end with an End Sub statement. All of your subroutine's logic appears in between these two mighty jaws.
01 Sub ShowIngredients(ByVal gender As Char) 02 Dim theMessage As String = "Unknown." 03 If (gender = "M"c) Then 04 theMessage = "Snips and snails and puppy dog tails." 05 ElseIf (gender = "F"c) Then 06 theMessage = "Sugar and spice and everything nice." 07 End If 08 MsgBox(theMessage) 09 End Sub
Line 01 shows the subroutine's declaration line in its simplest form; throughout the book, you will find that there are additional keywords that decorate procedure declarations to change their behavior. The statement begins with the Sub keyword (for subroutine), followed by the name of the procedure, ShowIngredients.
The parentheses following this name contain the subroutine's parameters. Parameters allow another block of code that will use this procedure to pass data into the procedure, and optionally receive data back. You can include any number of parameters in the subroutine definition; simply separate them by commas. Each parameter specifies the name as it will be used in the procedure (gender in the sample) and its data type (Char). The arguments are treated as declared variables within the procedure, as is done with gender on lines 03 and 05.
The values supplied by the calling code are known as arguments. All arguments are passed by value or by reference. In the sample code, the argument passed into gender will be passed by value, as specified through the ByVal keyword. The related ByRef keyword indicates an argument to be passed by reference. If you don't include either keyword, ByVal is assumed. This passing method impacts whether changes made to the argument within the local procedure are propagated back to the calling code. However, the ability to update the original data is also influenced by whether the data is a value type or a reference type. Table 2-3 indicates the behavior for each combination of passing method and data type.
In most cases, if you are interested in modifying the value of a parameter and having the changes return to the caller, use ByRef; otherwise, use ByVal.
Lines 02 through 08 in the sample code comprise the body of the procedure, where all of your logic appears. Any variables to be used solely in the routine are also defined here, as with the theMessage variable on line 02. The subroutine always concludes with an End Sub statement.
The syntax of a function differs only slightly from subroutines, to support a return value.
01 Function IsPrime(ByVal source As Long) As Boolean 02 ' ----- Determine if source is a prime number. 03 Dim testValue As Long 04 If (source < 2) Then 05 Return False 06 ElseIf (source > 2) Then 07 For testValue = 2 To source \ 2& 08 If ((source Mod testValue) = 0) Then 09 Return False 10 End If 11 Next testValue 12 End If 13 Return True 14 End Function
As with subroutines, the function's declaration line appears first (line 01), followed by the body (lines 02 through 13) and the closing End Function statement (line 14). The declaration line includes an extra data type definition after the parameter list. This is the data type of the final value to be returned to the calling code. Use this return value in the calling code just like any other value or variable. For example, the following line calls the IsPrime function and stores its Boolean result in a variable.
primeResult = IsPrime(23)
To indicate the value to return, use the Return statement (described later in the chapter). The sample code does this on lines 05, 09, and 13. (An older VB 6.0 syntax that lets you assign the return value to the name of the function still works.)
A little earlier I mentioned fields, variables or constants that appear within a class, but outside of any procedure definition.
01 Class PercentRange 02 Public Percent As Integer 03 End Class
Properties are similar to fields; they are used like class-level variables or constants. But they are programmed like functions, accepting parameters, having return values, and including as much logic as you require.
Properties are often used to protect private class data with logic that weeds out inappropriate values. The following class defines a single property that provides access to the hidden related field.
01 Class PercentRange 02 ' ----- Stores a percent from 0 to 100 only. 03 Private savedPercent As Integer 04 Public Property Percent() As Integer 05 Get 06 Return savedPercent 07 End Get 08 Set(ByVal value As Integer) 09 If (value < 0) Then 10 savedPercent = 0 11 ElseIf (value > 100) Then 12 savedPercent = 100 13 Else 14 savedPercent = value 15 End If 16 End Set 17 End Property 18 End Class
The Percent property (lines 04 to 17) protects access to the savedPercent field (line 03), correcting any caller-supplied values that exceed the 0 to 100 range. Properties include separate assignment and retrieval components, also called accessors. The Get accessor (lines 05 to 07) returns the property's monitored value to the caller. The Set accessor (lines 08 to 16) lets the caller modify the value of the property.
The property declaration statement (line 04) includes a data type that matches the data type passed into the Set accessor (line 08). This is the data type of the value set or retrieved by the caller. To use this sample Percent property, create an instance of the PercentRange class, and then use the property.
Dim activePercent As New PercentRange activePercent.Percent = 107 ' An out-of-range Integer MsgBox(activePercent.Percent) ' Displays "100", not "107"
You can create read-only or write-only properties by including the ReadOnly or WriteOnly keyword just before the Property keyword in the declaration statement (line 04), and leaving out the unneeded accessor.
Properties do not need to be tied to fields. You can use properties to get and set any type of value, and store it or act upon it in any manner you wish.
Where to Put Your Procedures
Back in the good ol' days of Visual Basic 6.0, procedures could appear just about anywhere in your source code files. You would open a source file, type a function, and go; it was that easy. With the move to .NET, all Visual Basic procedures must now appear within a defined class (or a structure or module).
Class Employee Sub StartVacation() ... End Sub Function TotalVacationTaken() As Double ... End Function End Class
When you create instances of your class later in code, the methods can be called directly through the object instance.
Dim executive As New Employee ... executive.StartVacation()
Chapter 8 shows you how to use and build classes.