I have already described the convenience of using Property Get and Let procedures instead of plain Public variables in a class: You get more control, you can validate data assigned to the property, you can trace the execution flow, and so on. But here’s one more interesting detail that you should be aware of. Even if you declare a Public variable, what Visual Basic actually does is create a hidden pair of Property procedures for you and calls them whenever you reference the property from outside the class:
‘ Inside the CPerson class
Public Height As Single ‘ Height in inches
‘ Outside the class
pers.Height = 70.25 ‘ This calls a hidden Property Let procedure.
Apart from a slight performance hit—invoking a procedure is surely slower than accessing a variable—this Visual Basic behavior doesn’t appear to be a detail worth mentioning. Unfortunately, this isn’t the case. Let’s suppose that you want to convert all your measurements into centimeters, so you prepare a simple procedure that does the job with its ByRef argument:
‘ In a standard BAS module
Sub ToCentimeters (value As Single)
‘ Value is received by reference, therefore it can be changed.
value = value * 2.54
End Sub
You think you can legitimately expect an easy conversion for your objects’ properties, as follows:
ToCentimeters pers.Height ‘ Doesn’t work!
The reason the preceding approach fails should be clear, now that you know that Public variables are implemented as hidden procedures. In fact, when you pass the pers.Height value to the ToCentimeters procedure you’re passing the result of an expression, not an actual memory address. Therefore, the routine has no address to which to deliver the new value, and the result of the conversion is lost.
Caution Microsoft changed the way the Public variables in class modules are implemented. In Visual Basic 4, these variables weren’t encapsulated in hidden property procedures; therefore, they could be modified if passed to a procedure through a ByRef argument. This implementation detail changed when Visual Basic 5 was released, and many Visual Basic 4 programmers had to rework their code to comply with the new style by creating a temporary variable that actually receives the new value:
‘ The fix that VB4 developers had to apply when porting to VB5
Dim temp As Single
temp = pers.Height
ToCentimeter temp
pers.Height = temp
This code is neither elegant nor efficient. Worse, since this technique isn’t clearly documented, many programmers had to figure it out on their own. If you are about to port some Visual Basic 4 code to versions 5 or 6, don’t be caught off guard.
Anyway, here’s yet another untold episode of the story. What I have described so far is what happens when you reference the Public variable from outside the class. If you invoke the external procedure from inside the class module and pass it your variable, everything works as expected. In other words, you can write this code in the CPerson class:
‘ Inside the CPerson class
ToCentimeter Height ‘ It works!
and the Height property will be correctly updated. In this case, the value passed is the address of the variable, not the return value of a hidden procedure. This point is important if you want to move code from outside the class to inside the class (or vice versa) because you must be prepared to deal with subtle issues like this one.
Caution One last note, just to add confusion to confusion: If you prefix the properties in your class module with the Me keyword, they’re again seen as properties instead of variables and Visual Basic invokes the hidden procedure instead of using the variable address. Therefore, this code won’t work even inside the class module:
ToCentimeter Me.Height ‘ It doesn’t work!
Saturday, December 26, 2009
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment