Previous Section  < Day Day Up >  Next Section

3.8. Operator Overloading

Built-in operators such as + and - are used so instinctively that one rarely thinks of them as a predefined implementation for manipulating intrinsic types. In C#, for example, the + operator is used for addition or concatenation depending on the data types involved. Clearly, each must be supported by different underlying code. Because the compiler knows what a numeric and string type represent, it is quite capable of doing this. It makes sense then that these operators cannot be applied to custom classes or structures of which the compiler has no knowledge.

It turns out that C# provides a mechanism referred to as operator overloading that enables a class to implement code that determines how the class responds to the operator. The code for overloading an operator is syntactically similar to that of a method:

public static <return type> operator <op> ( parameter list)

{ implementation code}

Several rules govern its usage:

  • The public and static modifiers are required.

  • The return type is the class type when working with classes. It can never be void.

  • op is a binary, unary, or relational operator. Both equals (==) and not equals (!=) must be implemented in a relational pair.

  • Binary operators require two arguments; unary operators require one argument.

Operator overloading with classes does not have to be limited to geometric or spatial objects. The example shown in Listing 3-14 demonstrates how to use the concept to maintain stocks in a portfolio. It contains two classes: one that represents a stock (defined by its price, number of shares, and risk factor) and one that represents the portfolio of stocks. Two overloaded operators (+ and -) add and remove stocks from the portfolio.

Listing 3-14. Operator Overloading for Classes

using System;

class Portfolio


   public decimal risk;

   public decimal totValue;

   // Overloaded operator to add stock to Portfolio

   public static Portfolio operator + (Portfolio p,Stock s)


      decimal currVal  = p.totValue;

      decimal currRisk = p.risk;

      p.totValue = p.totValue + s.StockVal;

      p.risk = (currVal/p.totValue)*p.risk +

         (s.StockVal/p.totValue)* s.BetaVal;

      return p;


   // Overloaded operator to remove stock from Portfolio

   public static Portfolio operator - (Portfolio p,Stock s)


      p.totValue = p.totValue - s.StockVal;

      p.risk = p.risk - ((s.BetaVal-p.risk)


      return p;



class Stock


   private decimal value;

   private decimal beta; // risk increases with value

   public  Stock(decimal myBeta, decimal myValue,

                 int shares)


      value = (decimal) myValue * shares;

      beta = myBeta;


   public decimal StockVal

      { get {return value; } }

   public decimal BetaVal

      { get {return beta; } }


class MyApp


   public static void Main()


      Portfolio p = new Portfolio();

      // 200 shs of HPQ at $25, 100 shs of IBM @ $95

      Stock hpq  = new Stock(1.1M, 25M, 200);

      Stock ibm  = new Stock(1.05M, 95.0M, 100);

      p += hpq;   // Add hpq

      p += ibm;   // Add ibm

      Console.Write("value:{0} ",p.totValue.ToString());

      Console.WriteLine(" risk: {0}",


      // value = 14,500 and risk = 1.07

      p -= ibm;   // Remove ibm from portfolio

      Console.Write("value:{0} ",p.totValue.ToString());

      Console.Write(" risk: {0}",p.risk.ToString("#.00"));

      // value = 5000 and risk = 1.10



The addition or deletion of a stock causes the portfolio total value and weighted risk factor to be adjusted. For example, when both stocks are added to the portfolio, the risk is 1.07. Remove ibm and the risk is 1.10, the risk of hpq alone.

When choosing to implement operator overloading, be aware that .NET languages are not required to support it. The easiest way to provide interoperability for those languages (such as Visual Basic.NET) lacking this feature is to include an additional class member that performs the same function:

public static Portfolio AddStocks ( Portfolio p, Stock s)

{ return p + s; }

In this case, the code exposes a public method whose implementation calls the overloaded method.

Another approach is to take advantage of the fact that language interaction occurs at the Intermediate Language level and that each operator is represented in the IL by a hidden method. Thus, if a language knows how to invoke this method, it can access the operator.

The ECMA standard provides a list of method names that correspond to each operator. For example, the + and & used in the preceding code are represented by op_Addition and op_BitwiseAnd, respectively. A language would access the overloaded + operator with its own syntactic variation of the following code:

newPortfolio = P.op_Addition(P, s)

Either approach works, but relying on assembly language is probably less appealing than providing a custom public method.

Although the discussion has been on classes, operator overloading also can be applied to simple data types. For example, you could define your own exponentiation operator for integers.

    Previous Section  < Day Day Up >  Next Section