Visual Basic defines operators for expressions that use standard data types such as Integers and Boolean values. It defines a few operators such as Is and IsNot for objects, but operators such as * and Mod don’t make sense for objects in general.
Nevertheless, you can also define those operators for your structures and classes, if you like, by using the Operator statement. This is a more advanced topic, so if you’re new to Visual Basic, you may want to skip this section and come back to it later, perhaps after you have read Chapter 23, “Classes and Structures.”
The general syntax for operator overloading is:
[ <attributes> ] Public [ Overloads ] Shared [ Shadows ] _
[ Widening | Narrowing ] Operator symbol ( operands ) As type
...
End Operator
The parts of this declaration are:
Operator overloading is subject to several constraints:
If you define an operator, Visual Basic automatically provides the corresponding assignment operator. For example, if you define the + operator, Visual Basic provides the += assignment operator.
Although you cannot use the IsTrue and IsFalse operators directly, you can use them indirectly. If you define IsTrue for a class, Visual Basic uses it to determine whether an object should be treated as True in a Boolean expression. For example, the following statement uses the IsTrue operator to decide whether the object c1 should be considered True:
if c1 Then ...
If you define the And and IsFalse operators, Visual Basic uses them to handle the AndAlso operator as well. For this to work, the And operator must return the same type of class or structure where you define it. For example, suppose you have defined And and IsFalse for the Composite class and suppose variables c1, c2, and c3 are all instances of this class. Then consider the following statement:
c3 = c1 AndAlso c2
Visual Basic uses IsFalse to evaluate c1. If IsFalse returns True, the program doesn’t bother to evaluate c2. Instead it assumes the whole statement is False and returns a False value. Because IsFalse returned True for c1, Visual Basic knows that c1 is a False value, so it sets c3 equal to c1.
This is pretty confusing. It may make more sense if you think about how Visual Basic evaluates Boolean expressions that use the normal AndAlso operator.
Similarly, if you define the Or and IsTrue operators, Visual Basic automatically provides the OrElse operator.
Although you generally cannot make two versions of a function in Visual Basic that differ only in their return types, you can do that for CType conversion operators. When the program tries to make a conversion, Visual Basic can tell by the type of the result which conversion operator to use.
Example program ComplexNumbers, which is available for download on the book’s website, uses the following code to define a Complex class that represents a complex number. It defines +, −, and * operators to implement normal addition, subtraction, and multiplication, respectively, on complex numbers. It also defines =, <>, and unary negation operators, and conversion operators that convert a Complex object into a Double and vice versa.
Public Class Complex
Public Re As Double
Public Im As Double
' Constructors.
Public Sub New()
End Sub
Public Sub New(ByVal real_part As Double, ByVal imaginary_part As Double)
Re = real_part
Im = imaginary_part
End Sub
' ToString.
Public Overrides Function ToString() As String
Dim txt As String = Re.ToString
If Im < 0 Then
txt &= " - " & Math.Abs(Im).ToString
Else
txt &= " + " & Im.ToString
End If
Return txt & "i"
End Function
' Operators.
Public Shared Operator *(ByVal c1 As Complex, ByVal c2 As Complex) _
As Complex
Return New Complex(
c1.Re * c2.Re - c1.Im * c2.Im,
c1.Re * c2.Im + c1.Im * c2.Re)
End Operator
Public Shared Operator +(ByVal c1 As Complex, ByVal c2 As Complex) _
As Complex
Return New Complex(
c1.Re + c2.Re,
c1.Im + c2.Im)
End Operator
Public Shared Operator -(ByVal c1 As Complex, ByVal c2 As Complex) _
As Complex
Return New Complex(
c1.Re - c2.Re,
c1.Im - c2.Im)
End Operator
Public Shared Operator =(ByVal c1 As Complex, ByVal c2 As Complex) _
As Boolean
Return (c1.Re = c2.Re) AndAlso (c1.Im = c2.Im)
End Operator
Public Shared Operator <>(ByVal c1 As Complex, ByVal c2 As Complex) _
As Boolean
Return (c1.Re <> c2.Re) OrElse (c1.Im <> c2.Im)
End Operator
Public Shared Operator -(ByVal c1 As Complex) As Complex
Return New Complex(-c1.Re, -c1.Im)
End Operator
Public Shared Narrowing Operator CType(ByVal c1 As Complex) As Double
Return System.Math.Sqrt(c1.Re * c1.Re + c1.Im * c1.Im)
End Operator
Public Shared Widening Operator CType(ByVal d As Double) As Complex
Return New Complex(d, 0)
End Operator
End Class
It is easy to get carried away with operator overloading. Just because you can define an operator for a class doesn’t mean you should. For example, you might be able to concoct some meaning for addition with the Employee class, but it would probably be a counterintuitive operation. You would probably be better off writing a subroutine or function with a meaningful name instead of using an ambiguous operator such as + or >>.