Overloading Operators in VB.NET 2.0

Although you do not need to write overloaded operators every day, this feature certainly puts the latest version of VB.NET (whether you call it 2.0 or 8.0—there is some confusion in this area) on par with even the most powerful object-oriented languages. This article demonstrates a step-by-step process for writing custom operators, including a brief explanation for neophytes. Of course, if you didn’t like VB.NET because of its differences from VB6, you probably won’t get too excited about the ability to overload operators in VB.NET 2.0.

What Operators Are and Why You Overload Them

Programming has a rich history based in mathematics. Mathematics is steeped in meaningful symbols, operators, and operands. Operators are symbols that perform a function and operands are the things on which operators operate.

Operators typically indicate how many operands they use. Usually, you’ll encounter unary, binary, and ternary operators. Unary means one operand, binary means two, and ternary means three. “Not” is an example of a unary operator; “+” is an example of a binary operator; and “?:” is an example of a ternary operator. (I have never seen a quaternary operator.)

Operators are convenient because they are quick to write and they are familiar, especially in arithmetic operations. For example, “&” and “+” are Boolean and arithmetic operators, but you can also used them to perform string concatenation for string operands. Clearly, operators have had multiple—or overloaded—meanings for some time. A natural evolution is this ability extending to us programmers.

Basic Guidelines for Overloading Operators

You should follow a few basic guidelines for overloading operators to either get past the compiler or avoid confusing people:

  • Don’t change an operator’s semantic meaning. The result of an operator should be intuitive.
  • Make certain overloaded operators are shared methods.
  • Overload operators in pairs, if a symmetric pair exists. These are the pairs of operators: “=” and “<>”; “>” and “>”; “>=” and “<=”; and IsTrue and IsFalse.
  • You cannot overload assignment (for example, the “=” operator in the preceding guideline is the equality-test operator.).
  • You can overload only the operators listed in Table 1.

    Table 1: Operators That Can Be Overloaded in .NET 2.0

    Operator Operand Count Description
    + Unary Positive
    Unary Negative
    IsFalse Unary Is False test
    IsTrue Unary Is True test
    Not Unary Negation
    + Binary Addition
    Binary Subtraction
    * Binary Multiplication
    / Binary Floating-point division
    Binary Integer division
    & Binary Concatenation
    ^ Binary Exponentiation
    >> Binary Shift right
    << Binary Shift left
    = Binary Equality; assignment
    cannot be overloaded
    <> Binary Not equal
    > Binary Greater than
    < Binary Less than
    >= Binary Greater than or equal to
    <= Binary Less than or equal to
    And Binary Bitwise and
    Like Binary String pattern matching
    Mod Binary Modulo division
    Or Binary Bitwise or
    Xor Binary Bitwise xor
    CType Unary Type conversion
  • Finally, don’t assume that operators have been overloaded correctly or that others have defined all possible operators.

Defining a Named Method

Generic methods in VB.NET must be shared. They must have the same number of arguments as your operator will have. Thus, if you are overloading addition, you need a shared method with two arguments and a return type.

Suppose your problem domain needs a distance measured in feet and inches. (Don’t worry; you could localize this class to switch to metric units, but that isn’t relevant to this discussion.) To support your problem domain, you could easily define a class Distance that stores feet and inches as integers (see Listing 1).

Listing 1: A Distance Class That Stores Feet and Inches

Public Class Distance
  Private FFeet As Integer
  Private FInches As Integer

  Public Sub New(ByVal Feet As Integer, ByVal Inches As Integer)
    FFeet = Feet
    If (Inches > 12) Then
      FFeet += (Inches / 12)
      FInches = (Inches Mod 12)
      FInches = Inches
    End If
  End Sub

  Public Sub New(ByVal Inches As Integer)
    FFeet = (Inches / 12)
    FInches = (Inches Mod 12)
  End Sub

  Public Property Feet() As Integer
      Return FFeet
    End Get
    Set(ByVal value As Integer)
      FFeet = value
    End Set
  End Property

  Public Property Inches() As Integer
      Return FInches
    End Get
    Set(ByVal value As Integer)
      If (value > 12) Then
        FFeet += (value / 12)
        FInches = (value Mod 12)
        FInches = value
      End If
    End Set
  End Property

  Public Overrides Function ToString() As String
    Return FFeet & "ft " & FInches & "in"
  End Function

End Class

Listing 1 converts all inches greater or equal to 12 to feet. For example, if you set the inches field using the Inches property, 14 inches becomes 1 foot, 2 inches. Next, you can support basic arithmetic operations by defining addition and subtraction. Following your named methods guidelines, you get the named methods in Listing 2.

Listing 2: Operations Implemented as Named Methods Separate Algorithm from Syntax

  Public Shared Function Add(ByVal lhs As Distance, _
                             ByVal rhs As Distance) As Distance
    Return New Distance(lhs.Feet + rhs.Feet, lhs.Inches + rhs.Inches)
  End Function

  Public Shared Function Subtract(ByVal lhs As Distance, _
    ByVal rhs As Distance) As Distance
    Return New Distance(lhs.Feet - rhs.Feet, lhs.Inches - rhs.Inches)
  End Function

After Listing 2, you can perform operations such as Distance.Add(Distance1, Distance2). All that remains is implementing the overloaded operators.

More by Author

Must Read