[Contents] [Next]

Syntax and Example

As I've said, operator overloading is a means of calling a method. To redefine an operator for a class, you need only use the following pattern, where op is the operator you're overloading: -

public static retval operator op ( object1 [, object2 ]) -

Keep in mind the following facts when using operator overloading: -

  • All overloaded operator methods must be defined as public and static.
  • Technically, retval (the return value) can be any type. However, it's common practice to return the type for which the method is being defined with the exception of the true and false operators, which should always return a Boolean value.
  • The number of arguments passed (object1, object2) depends on the type of operator being overloaded. If a unary operator (an operator having a single operand) is being overloaded, there will be one argument. If a binary operator (an operator taking two operands) is being overloaded, two arguments are passed.
  • In the case of a unary operator, the argument to the method must be the same type as that of the enclosing class or struct. In other words, if you redefine the ! unary operator for a class called Foo, that method must take as its only argument a variable of type Foo.
  • If the operator being overloaded is a binary operator, the first argument must be the same type as that of the enclosing class and the second argument can be any type.

In the previous section's pseudocode, I used the += operator with an Invoice class. For reasons you'll soon understand, you can't actually overload these compound operators. You can overload only the "base" operator-in this case, the +. Here's the syntax used to define the Invoice class's operator+ method: -

public static Invoice operator+ (Invoice invoice1, Invoice invoice2)
{
    // Create a new Invoice object.
    // Add the desired contents from
    // invoice1 to the new Invoice object.
    // Add the desired contents from
    // invoice2 to the new Invoice object.
    // Return the new Invoice object.
 }

Let's look at a more substantial example now, one with two main classes: Invoice and InvoiceDetailLine. The Invoice class has a member variable of type ArrayList that represents a collection of all invoice detail lines. To allow for the aggregation of detail lines for multiple invoices, I've overloaded the + operator. (See the operator + method below for details.) The Invoice.operator+ method creates a new Invoice object and iterates through both invoice objects' arrays of invoice detail lines, adding each detail line to the new Invoice object. This Invoice object is then returned to the caller. Obviously, in a real-world invoicing module, this would be much more complex, but the point here is to show somewhat realistically how operator overloading could be used.

using System;
using System.Collections;
class InvoiceDetailLine
{
    double lineTotal;
    public double LineTotal
    {
        get
        {
            return this.lineTotal;
        }
    }
    public InvoiceDetailLine(double LineTotal)
    {
        this.lineTotal = LineTotal;
    }
}
class Invoice
{
    public ArrayList DetailLines;
    public Invoice()
    {
        DetailLines = new ArrayList();
    }
    public void PrintInvoice()
    {
        Console.WriteLine("\nLine Nbr\tTotal");
        int i = 1;
        double total = 0;
        foreach(InvoiceDetailLine detailLine in DetailLines)
        {
            Console.WriteLine("{0}\t\t{1}", i++, detailLine.LineTotal);
            total += detailLine.LineTotal;
        }
        Console.WriteLine("=====\t\t===");
        Console.WriteLine("Total\t\t{1}", i++, total);
    }
    public static Invoice operator+ (Invoice invoice1, Invoice invoice2)
    {
        Invoice returnInvoice = new Invoice();
        foreach (InvoiceDetailLine detailLine in invoice1.DetailLines)
        {
            returnInvoice.DetailLines.Add(detailLine);
        }
        foreach (InvoiceDetailLine detailLine in invoice2.DetailLines)
        {
            returnInvoice.DetailLines.Add(detailLine);
        }
        return returnInvoice;
    }
}
class InvoiceAddApp
{
    public static void Main()
    {
        Invoice i1 = new Invoice();
        for (int i = 0; i < 2; i++)
        {
            i1.DetailLines.Add(new InvoiceDetailLine(i + 1));
        }
        Invoice i2 = new Invoice();
        for (int i = 0; i < 2; i++)
        {
            i2.DetailLines.Add(new InvoiceDetailLine(i + 1));
        }
        Invoice summaryInvoice = i1 + i2;
        summaryInvoice.PrintInvoice();
    }
}

[Contents] [Next]