Using the operator Keyword

In C#, operators are static methods. The return value of an operator represents the result of an operation. The operator’s parameters are the operands.

You can define an addition operator for a Fraction class as you would any other class method, but with a bit of a difference. Instead of a method name, you use the C# syntax of combining the operator keyword with the plus sign (+) operator, combined with the keyword static. For example, the overloaded addition operator (the operator+ method) takes two Fraction objects (the fractions you want to add) as parameters and returns a reference to another Fraction object representing the sum of the two parameters. Here is its signature:

public static Fraction operator+(Fraction lhs, Fraction rhs)

And here’s what you can do with it. Assume, for instance, that you’ve defined two fractions representing the portion of a pie you’ve eaten for breakfast and lunch, respectively. (You love pie.)

Fraction pieIAteForBreakfast = new Fraction(1,2); // 1/2 of a pie
Fraction pieIAteForLunch = new Fraction(1,3);     // 1/3 of a pie

The overloaded operator+ allows you to figure out how much pie you’ve eaten in total. (And there’s still 1/6 of the pie leftover for dinner!) You would write:

Fraction totalPigOut = pieIAteForBreakfast + pieIAteForLunch;

The compiler takes the first operand (pieIAteForBreakfast) and passes it to operator+ as the parameter lhs; it passes the second operand (pieIAteForLunch) as rhs. These two Fractions are then added, and the result is returned and assigned to the Fraction object named totalPigOut.

Tip

It is our convention to name the parameters to a binary operator lhs and rhs. A binary operator is an operator that takes two operands. The parameter name lhs stands for “lefthand side” and reminds us that the first parameter represents the lefthand side of the operation. Similarly, rhs stands for “righthand side.”

To see how this works, you’ll create a Fraction class, as described previously. We’ll show you the complete listing first, in Example 12-1, and then we’ll take it apart and explain what it does.

Example 12-1. Implementing operator+ for Fraction isn’t difficult; you define it as you would any method of the class, but using the keyword operator

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Example_12_1_ _ _ _Overloading_Addition
{
    public class Fraction
    {
        private int numerator;
        private int denominator;

        // create a fraction by passing in the numerator
        // and denominator
        public Fraction(int numerator, int denominator)
        {
            this.numerator = numerator;
            this.denominator = denominator;
        }

        // overloaded operator + takes two fractions
        // and returns their sum
        public static Fraction operator+ (Fraction lhs, Fraction rhs)
        {
            // like fractions (shared denominator) can be added
            // by adding their numerators
            if (lhs.denominator == rhs.denominator)
            {
                return new Fraction(lhs.numerator + rhs.numerator,
                                    lhs.denominator);
            }

            // simplistic solution for unlike fractions
            // 1/2 + 3/4 == (1*4) + (3*2) / (2*4) == 10/8
            // this method does not reduce.
            int firstProduct = lhs.numerator * rhs.denominator;
            int secondProduct = rhs.numerator * lhs.denominator;
            return new Fraction( firstProduct + secondProduct,
                                 lhs.denominator * rhs.denominator );
        }

        // return a string representation of the fraction
        public override string ToString()
        {
            String s = numerator.ToString() + "/" + denominator.ToString();
            return s;
        }
    }

    public class Tester
    {
        public void Run()
        {
            Fraction firstFraction = new Fraction(3, 4);
            Console.WriteLine("firstFraction: {0}", firstFraction.ToString());

            Fraction secondFraction = new Fraction(2, 4);
            Console.WriteLine("secondFraction: {0}", secondFraction.ToString());

            Fraction sumOfTwoFractions = firstFraction + secondFraction;
            Console.WriteLine( "firstFraction + secondFraction =
                         sumOfTwoFractions: {0}", sumOfTwoFractions.ToString());

        }
        static void Main()
        {
            Tester t = new Tester();
            t.Run();
        }
    }
}

The output looks like this:

firstFraction: 3/4
secondFraction: 2/4
firstFraction + secondFraction = sumOfTwoFractions: 5/4

Let’s take this one step at a time, so you can see how this class works. In Example 12-1, you start by creating a Fraction class. The private member data is the numerator and denominator, stored as integers:

public class Fraction
{
    private int numerator;
    private int denominator;

The constructor just initializes these values; that’s simple enough.

The overloaded addition operator takes two Fraction objects, returns a Fraction, and is marked static:

public static Fraction operator+ (Fraction lhs, Fraction rhs)
{

As you’d expect for adding fractions, if the denominators for the fractions are the same, you add the numerators and return a new Fraction object created by passing in the sum of the numerators as the new numerator and the shared denominator as the new denominator:

if (lhs.denominator == rhs.denominator)
{
     return new Fraction(lhs.numerator + rhs.numerator,
                         lhs.denominator);
}

The Fraction object’s firstFraction and secondFraction are passed in to the overloaded addition operator as lhs and rhs, respectively. The new Fraction is returned to the calling method, Run(), where it is assigned to sumOfTwoFractions:

Fraction sumOfTwoFractions = firstFraction + secondFraction;
Console.WriteLine( "firstFraction + secondFraction = sumOfTwoFractions: {0}",
                      sumOfTwoFractions.ToString() );

Back in the implementation of the operator, if the denominators are different, you cross-multiply before adding, which is the standard method for adding unlike fractions:

int firstProduct = lhs.numerator * rhs.denominator;
int secondProduct = rhs.numerator * lhs.denominator;
return new Fraction( firstProduct + secondProduct,
                     lhs.denominator * rhs.denominator );

The two local variables, firstProduct and secondProduct, are temporary; they are destroyed when the method returns. The new Fraction created, however, is not temporary; it returned to Run() as in the case where the denominators are equal.

Tip

A good Fraction class would, no doubt, implement all the arithmetic operators (addition, subtraction, multiplication, division). To overload the multiplication operator, you would write operator*; to overload the division operator, you would write operator/.

The Fraction class also overrides the ToString() method (inherited from Object, as discussed in Chapter 11) to allow you to display the fractions by passing them to Console.WriteLine():

public override string ToString()
{
    String s = numerator.ToString() + "/" + denominator.ToString();
    return s;
}

When you run this application, you can see that the ToString() method works as planned, and the overloaded operator allows you to add firstFraction and secondFraction as intuitively as though they were ints.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset