Do You Really Understand Parameter Passing In Visual Basic .NET?
So, you've taken the plunge and started to move from Visual Basic 6.0 to Visual Basic .NET. Good! You're going to like what you see. Be forewarned, however, that you should expect your fair share of "flat forehead" hiccups along the way. You know...those mistakes after which you slam the heel of your hand to your forehead and ask yourself how you could make such a silly mistake. Relax. Any programmer who doesn't have a small dent in his forehead is just getting started in the business.
The purpose of this article is to explain a very fundamental change between Visual Basic 6.0 and Visual Basic .NET. A thorough understanding of this difference will help you make the conversion a little easier and add a new dimension to your debugging talents. For example, consider the code shown in Listings 1 and 2. (We'll ignore the argument list for the Form1_Load event in Visual Basic .NET version to simplify things a bit.)
Listing 1. Square a Long: Visual Basic 6.0
Private Sub Form1_Load() Dim n As Long n = 10 SquareIt n End Sub Public Sub SquareIt(val As Long) val = val * val End Sub
Listing 2. Square a Long: Visual Basic .NET
Private Sub Form1_Load() Dim n As Long n = 10 SquareIt n End Sub Public Sub SquareIt(ByVal val As Long) val = val * val End Sub
You can type the Visual Basic 6.0 code shown in Listing 1 into Visual Basic .NET (VB6 and VBN, respectively, from now on) without change. The VB6 code in Listing 1 produces the code shown in Listing 2 for the VBN environment. If you place a breakpoint on the End Sub for the Form1_Load event and run both versions, you will find that n equals 100 in the VB6 program, but is equal to 10 in the VBN program. Casual inspection of the program suggests that the innocuous ByVal keyword in the SquareIt() argument list is the likely culprit causing the difference. Finding that difference is easy. Truly understanding the difference is a little more involved.
Defining a Variable
Some programmers are a bit sloppy when they use the words "define" and "declare" with respect to data. They are not the same terms. Consider what happens with the simple Dim statements shown in Listings 1 and 2. In the VBN environment, the fact that we don't see the dreaded "squiggly line" anywhere under the Dim statement line tells us that there are no syntax errors. A syntax error occurs when a statement does not abide by the rules of the language. Other errors may occur later when we run the program. For example, a semantic error can occur even when we obey the syntax rules, but use the language elements out of context. For example, the sentence "The dog meowed" obeys the syntax rules of English, but the noun and verb are used out of context, resulting in a semantic error. VBN does an excellent job of catching syntax errors, however.
Because there are no syntax errors in the Dim statement, VBN then looks through its symbol table to see whether a variable Named n is already defined at the current scope level. A symbol table is a table of information that VBN maintains about every data item being used in the program. A very simplified symbol table is shown in Table 1.
Table 1. A Simplified Symbol Table
Variable Name |
Data Type |
Scope |
lvalue |
(more attributes...) |
n |
2 |
3 |
? |
|
... |
|
|
|
|
If there had been a variable named n already defined in the symbol table, VBN would have issued the following error message:
Local variable 'n' is already declared in the current block.
However, because no other variable named n exists in the symbol table at the same scope level, VBN proceeds to the next step.
VBN now sends a message to Windows, in effect saying the following: "Hey, Windows! It's me, VBN. My programmer needs eight bytes of storage for a Long data type. How's it looking?" The Windows Memory Manager (WMM) will search the operating system's free memory pool and will probably find a free eight-byte memory block. WMM then sends the following message back to VBN: "Hey, VBN! It's me, WMM. Your programmer can use the eight-byte memory block that starts at memory address 80,000." (If WMM could not find the requested storage, VBN would have issued an out-of-memory error message.)
Upon receiving the good news from WMM, VBN fills in the lvalue column in Table 1 with 80,000. It is at this point that we have defined the variable named n. A data definition for a variable occurs if, and only if, storage is allocated for the variable by the operating system. If storage is not allocated for the data item, it is not a data definition. More on this later...