You can overload pretty much any of Visual Basic's standard operators (except for Is and IsNot), plus a few other features. This section describes each overloadable operator, grouped by general type. Each section includes a table of operators. To overload an operator in a class, use the name in the Operator column as the function name. If there were an operator named XX, the matching Operator statement would be as follows.
Public Shared Operator XX(...)
Visual Basic defines ten mathematical or pseudo-mathematical operators. All but one of these exists to manipulate numbers. The leftover operator is the string concatenation operator (&), which works with strings, but kind of looks like the other mathematical operators in its syntax and use.
Two of the operators, plus (+) and minus (), are both unary and binary operators. The minus sign () works as a unary "negation" operator (as in "5"), and also as a binary "subtraction" operator (the common "5 2" syntax). When overloading these operators, the difference lies in the number of arguments included in the argument signature.
Public Shared Operator -(ByVal operand1 As SomeClass, _ ByVal operand2 As SomeClass) As SomeClass ' ----- This is the binary "subtraction" version. End Operator Public Shared Operator -(ByVal operand1 As SomeClass) _ As SomeClass ' ----- This is the unary "negation" version. End Operator
Table 12-1 lists the mathematical operators that support overloading.
Visual Basic includes seven basic comparison operators, most often used in If statements and similar expressions that require a Boolean conditional calculation. The Operator methods for these comparison operators have the same syntax as is used for mathematical operators, but most of them must be implemented in pairs. For example, if you overload the Less Than (<) operator, Visual Basic requires you to overload the Greater Than (>) operator within the same class, and for the same argument signature.
All comparison operators are Boolean operators. Although you can alter the data types of the arguments passed to the operator, they must all return a Boolean value.
Public Shared Operator <=(ByVal operand1 As SomeClass, _ ByVal operand2 As SomeClass) As Boolean ' ----- The <= operator returns a Boolean result. End Operator
Table 12-2 lists six of the seven basic comparison operators that you can overload. Each entry includes a "buddy" value that identifies the matching operator that must also be overloaded.
The seventh comparison operator is Like. In standard Visual Basic, it compares the first operand to a string "pattern," which is generally a set of matching characters and wildcards.
If (someValue Like somePattern) Then
You don't have to use the same pattern rules when overloading the Like operator, and you can accept any data type for the pattern operand, but you must still return a Boolean result.
Public Shared Operator Like(ByVal operand1 As Bumblebee, _ ByVal operand2 As Integer) As Boolean ' ----- See if Bumblebee matches an Integer pattern. End Operator
There is no "buddy" operator that you must implement when overloading the Like operator.
Bitwise and Logical Operators
Among the logical and bitwise operators included in Visual Basic, four already perform double duty as overloaded operators. The bitwise And, Or, Xor, and Not accept integer operands, generating a numeric result with values transformed at the individual bit level. They also work as logical operators, accepting and returning Boolean values, most often in conditional statements. But they can handle the stress of being overridden a little more.
When you do override these four operators, you are overriding the bitwise versions, not the logical versions. Basically, this means that you have control over the return value, and aren't required to make it Boolean.
Table 12-3 lists the eight overloadable bitwise and logical operators.
The CType Operator
The Visual Basic CType feature looks more like a function than an operator:
result = CType(source, type)
But looks are deceiving. It is not a true function, and as with the other conversion functions (like CInt), it is actually processed at compile time, long before the program even runs. By allowing you to overload it as an operator, Visual Basic enables you to create custom and special conversions between data types that don't seem compatible. The following method template converts a value of type Bumblebee to an Integer.
Public Shared Operator CType(ByVal operand1 As Bumblebee) _ As Integer ' ----- Perform conversion here, returning an Integer. End Operator
If you try to type that last block of code into Visual Basic, it will complain that you are missing either the "Widening" or "Narrowing" keyword (see Figure 12-1).
Figure 12-1. Visual Basic complains about all things wide and narrow
I mentioned widening and narrowing conversions in passing in Chapter 2, "Introducing Visual Basic," but let's examine them in more depth. When you convert between some core data types in Visual Basic, there is a chance that it will sometimes fail because the source value cannot fit into the destination value. This is true when converting a Short value to a Byte.
Dim quiteBig As Short = 5000 Dim quiteSmall As Byte ' ----- These next two lines will fail. quiteSmall = quiteBig quiteSmall = CByte(quiteBig)
And it's obvious why it fails: A Byte variable cannot hold the value 5000. But what about this code?
Dim quiteBig As Short = 5 Dim quiteSmall As Byte ' ----- These next two lines will succeed. quiteSmall = quiteBig quiteSmall = CByte(quiteBig)
It will run just fine, because 5 fits into a Byte variable with room to spare. (If Option Strict is set to On, the first assignment will still fail to compile.) Still, there is nothing to stop me from reassigning a value of 5000 to quiteBig and trying the assignment again. It's this potential for failure during conversion that is the issue.
When a conversion has the potential to fail due to the source data not being able to fully fit in the target variable, it's called a narrowing conversion. Narrowing conversions are a reality, and as long as you have checked the data before the conversion, there shouldn't be any reason to permanently restrict such conversions.
Widening conversions go in the opposite direction. They occur when any source value in the original data type will always fit easily in the target type. A widening conversion will always succeed as long as the source data is valid.
Visual Basic allows widening conversions to occur automatically, implicitly. You don't have to explicitly use CType to force the conversion. If you had a widening conversion from Bumblebee to Integer, and you had set Option Strict to On, the following code would work just fine.
Dim sourceValue As New Bumblebee Dim destValue As Integer = sourceValue
If the conversion from Bumblebee to Integer was narrowing, you would have to force the conversion using CType just so Visual Basic was sure you really wanted to do this.
Dim sourceValue As New Bumblebee Dim destValue As Integer = CType(sourceValue, Integer)
When you create custom conversions with the overloaded CType operator, you must inform Visual Basic whether the conversion is widening or narrowing by inserting either the Widening or Narrowing keyword between the Shared and Operator keywords.
Public Shared Narrowing Operator CType( _ ByVal operand1 As Bumblebee) As Integer ' ----- Perform narrowing conversion here. End Operator