MORE INFORMATION
Coercion between numeric types is pretty straightforward. Smaller types
(integer) coerced to larger types (double) simply have their value
assigned. Larger types (double) coerced to smaller types (integer) have
their value assigned, but generate an Overflow error if the smaller type
cannot contain the larger type's value. Other coercion rules are not as
obvious.
NOTE: Any type can be implicitly coerced to any other type (excluding
objects).
Source Type Coerced to Apply this rule
--------------------------------------------------------------
Integer Boolean 0=False, non-zero=True
Boolean Byte False=0, True=255
Boolean any numeric False=0, True=-1
(except Byte)
String Date String is analyzed for mm/dd/yy,
and so on
Date numeric type Coerce to Double and use
DateSerial(Double)
numeric type Date Use number as serial date, check
valid date range
numeric type Byte Error if negative
String numeric type Strings are treated as a Double
when they need to represent a
number
Some of these rules allow for simplified syntax when writing your code. For
example:
ReturnCode% = FunctionThatReturnsAnInteger()
If (ReturnCode%) Then ...
This piece of code takes advantage of the implicit Integer to Boolean
coercion and correctly evaluates the expression in the If statement.
Note on Strings as Numbers
Treating Strings as Doubles when they need to represent a number gives the
String the maximum possible range and nearly the best possible precision
(only Currency can have more precision, at a sacrifice in range). Because
these coercions are generated by the compiler, the rule must be decided up
front without regard to the actual content of the string.
Note that "treating as Double" is not quite the same as "coercing to
Double." For example, addition and subtraction operators treat Currency as
a preferable type to Double. Currency plus String will be treated as
Currency plus Double, which would use Currency addition. Thus the string
will be coerced directly to Currency.
Why Use Coercion Rules?
The largest reason is performance. Hard-coded coercion rules make Visual
Basic version 4.0 faster and more efficient and provide backward
compatibility to previous versions of Visual Basic. One of the big speed
advantages comes because Visual Basic version 4.0 now knows the data type
of control properties. Knowing the type of properties provides trememdous
performance advantages. Without it, for example, setting a property
required Basic to package the value in a Variant, and the control to unpack
and coerce it to the right type. Now the control knows it is receiving the
correct specific type, and Basic does a direct coercion to that type
without ever involving the overhead of a Variant.
Unexpected Results
The following code pieces show a few common scenarios where errors can be
generated by Visual Basic if types and coercion rules are not carefully
considered:
Dim I As Integer, J As Integer
Dim L As Long, M As Long
Dim S As String
I = 32767
L = 32767
M = 1
S = "Hello World!"
J = I + 1
' Overflow. Integer upper limit = 32767. No coercion applied.
J = I + M
' Overflow. I+M is coerced to a Long and the value 32768 is generated,
' but when the assignment operator is resolved, this Long value is
' coerced back to Integer (J's type) and overflows.
L = I + 1
' Overflow. Coercion is not applied until the assignment operator is
' resolved. I + 1 'Overflow's the temporary Integer variable created
' to resolve the plus operator.
If I Then Print "I is True"
If Not I Then Print "Not I is True"
' This prints both 'I is True and Not I is True', a logical
' contradiction. The value of I = 32767, which is non-zero and under
' the Integer to Boolean rule, is coerced to True. With 'Not I',
' the NOT operator is applied first, which produces -32768 which is
' also non-zero and, therefore, True.
The following scenario shows how implicit conversion can generate a variety
of unexpected results. You can add this code to a new program and run it
too see the output.
Private Sub Form_Click()
Call MySub(1, 23) '<-- Note: passing *numbers*!
End Sub
Private Sub MySub (a As String, b As String)
Debug.Print "a = "; a, , TypeName(a)
Debug.Print "b = "; b, , TypeName(b)
Debug.Print "a + b = "; a + b, , TypeName(a + b)
Debug.Print "a + b - 1 ="; a + b - 1, TypeName(a + b - 1)
Debug.Print "1 - a + b ="; 1 - a + b, TypeName(1 - a + b)
Debug.Print "a + b + 1 ="; a + b + 1, TypeName(a + b + 1)
Debug.Print "1 + a + b ="; 1 + a + b, TypeName(1 + a + b)
Debug.Print "(1 + b) / a ="; (1 + b) / a, TypeName((1 + b) / a)
End Sub
The output is:
a = 1 String
b = 23 String
a + b = 123 String
a + b - 1 = 122 Double
1 - a + b = 23 Double
a + b + 1 = 124 Double
1 + a + b = 25 Double
(1 + b) / a = 24 Double