Operator Overloading Fundamentals


Operator overloading is closely related to method overloading. To overload an operator, you use the operator keyword to define an operator method, which defines the action of the operator relative to its class.

There are two forms of operator methods: one for unary operators and one for binary operators. The general form for each is shown here:

 // General form for overloading a unary operator. public static ret-type operator op(param-type operand) {    // operations } // General form for overloading a binary operator. public static ret-type operator op(param-type1 operand1, param-type1 operand2) {    // operations }

Here, the operator that you are overloading, such as + or /, is substituted for op. The ret-type is the type of value returned by the specified operation. Although it can be of any type you choose, the return value is often of the same type as the class for which the operator is being overloaded. This correlation facilitates the use of the overloaded operator in expressions. For unary operators, the operand is passed in operand. For binary operators, the operands are passed in operand1 and operand2.

For unary operators, the operand must be of the same type as the class for which the operator is being defined. For binary operators, at least one of the operands must be of the same type as its class. Thus, you cannot overload any C# operators for objects that you have not created. For example, you can’t redefine + for int or string.

One other point: Operator parameters must not use the ref or out modifier.

Overloading Binary Operators

To see how operator overloading works, let’s start with an example that overloads two binary operators, the + and the . The following program creates a class called ThreeD, which maintains the coordinates of an object in three-dimensional space. The overloaded + adds the individual coordinates of one ThreeD object to another. The overloaded subtracts the coordinates of one object from the other.

 // An example of operator overloading. using System; // A three-dimensional coordinate class. class ThreeD {   int x, y, z; // 3-D coordinates   public ThreeD() { x = y = z = 0; }   public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }   // Overload binary +.   public static ThreeD operator +(ThreeD op1, ThreeD op2)   {     ThreeD result = new ThreeD();     /* This adds together the coordinates of the two points        and returns the result. */     result.x = op1.x + op2.x; // These are integer additions     result.y = op1.y + op2.y; // and the + retains its original     result.z = op1.z + op2.z; // meaning relative to them.     return result;   }   // Overload binary -.   public static ThreeD operator -(ThreeD op1, ThreeD op2)   {     ThreeD result = new ThreeD();     /* Notice the order of the operands. op1 is the left        operand and op2 is the right. */     result.x = op1.x - op2.x; // these are integer subtractions     result.y = op1.y - op2.y;     result.z = op1.z - op2.z;     return result;   }   // Show X, Y, Z coordinates.   public void show()   {     Console.WriteLine(x + ", " + y + ", " + z);   } } class ThreeDDemo {   public static void Main() {     ThreeD a = new ThreeD(1, 2, 3);     ThreeD b = new ThreeD(10, 10, 10);     ThreeD c = new ThreeD();     Console.Write("Here is a: ");     a.show();     Console.WriteLine();     Console.Write("Here is b: ");     b.show();     Console.WriteLine();     c = a + b; // add a and b together     Console.Write("Result of a + b: ");     c.show();     Console.WriteLine();     c = a + b + c; // add a, b and c together     Console.Write("Result of a + b + c: ");     c.show();     Console.WriteLine();     c = c - a; // subtract a     Console.Write("Result of c - a: ");     c.show();     Console.WriteLine();     c = c - b; // subtract b     Console.Write("Result of c - b: ");     c.show();     Console.WriteLine();   } }

This program produces the following output:

 Here is a: 1, 2, 3 Here is b: 10, 10, 10 Result of a + b: 11, 12, 13 Result of a + b + c: 22, 24, 26 Result of c - a: 21, 22, 23 Result of c - b: 11, 12, 13

Let’s examine the preceding program carefully, beginning with the overloaded operator +. When two objects of type ThreeD are operated on by the + operator, the magnitudes of their respective coordinates are added together, as shown in operator+( ). Notice, however, that this method does not modify the value of either operand. Instead, a new object of type ThreeD, which contains the result of the operation, is returned by the method. To understand why the + operation does not change the contents of either object, think about the standard arithmetic + operation as applied like this: 10+12. The outcome of this operation is 22, but neither 10 nor 12 is changed by it. Although there is no rule that prevents an overloaded operator from altering the value of one of its operands, it is best for the actions of an overloaded operator to be consistent with its usual meaning.

Notice that operator+( ) returns an object of type ThreeD. Although the method could have returned any valid C# type, the fact that it returns a ThreeD object allows the + operator to be used in compound expressions, such as a+b+c. Here, a+b generates a result that is of type ThreeD. This value can then be added to c. Had any other type of value been generated by a+b, such an expression would not work.

Here is another important point: when the coordinates are added together inside operator+( ), the addition of the individual coordinates results in an integer addition. This is because the individual coordinates, x, y, and z, are integer quantities. The fact that the + operator is overloaded for objects of type ThreeD has no effect on the + as it is applied to integer values.

Now, look at operator( ). The operator works just like the + operator except that the order of the parameters is important. Recall that addition is commutative, but subtraction is not. (That is, AB is not the same as BA!) For all binary operators, the first parameter to an operator method will contain the left operand. The second parameter will contain the one on the right. When implementing overloaded versions of the non-commutative operators, you must remember which operand is on the left and which is on the right.

Overloading Unary Operators

The unary operators are overloaded just like the binary operators. The main difference, of course, is that there is only one operand. For example, here is a method that overloads the unary minus for the ThreeD class:

 // Overload unary -. public static ThreeD operator -(ThreeD op) {   ThreeD result = new ThreeD();   result.x = -op.x;   result.y = -op.y;   result.z = -op.z;   return result; }

Here, a new object is created that contains the negated fields of the operand. This object is then returned. Notice that the operand is unchanged. Again, this is in keeping with the usual meaning of the unary minus. For example, in an expression such as this:

 a = -b

a receives the negation of b, but b is not changed.

There are, however, two cases in which an operator method will need to change the contents of an operand: ++ and . Since the usual meaning of these operators is increment and decrement, an overloaded ++ or should usually increment or decrement the operand. Thus, when overloading these two operators, the operand will usually be modified. For example, here is an operator++( ) method for the ThreeD class:

 // Overload unary ++. public static ThreeD operator ++(ThreeD op) {   // for ++, modify argument   op.x++;   op.y++;   op.z++;   return op; // operand is returned }

Notice that the object referred to by op is modified by this method. Thus, the operand in a ++ operation is incremented. The modified object is also returned. This is necessary to allow the ++ operator to be used in a larger expression.

Here is an expanded version of the previous example program that demonstrates the unary and the ++ operator:

 // More operator overloading. using System; // A three-dimensional coordinate class. class ThreeD {   int x, y, z; // 3-D coordinates   public ThreeD() { x = y = z = 0; }   public ThreeD(int i, int j, int k) { x = i; y = j; z = k; }   // Overload binary +.   public static ThreeD operator +(ThreeD op1, ThreeD op2)   {     ThreeD result = new ThreeD();     /* This adds together the coordinates of the two points        and returns the result. */     result.x = op1.x + op2.x;     result.y = op1.y + op2.y;     result.z = op1.z + op2.z;     return result;   }   // Overload binary -.   public static ThreeD operator -(ThreeD op1, ThreeD op2)   {     ThreeD result = new ThreeD();     /* Notice the order of the operands. op1 is the left        operand and op2 is the right. */     result.x = op1.x - op2.x;     result.y = op1.y - op2.y;     result.z = op1.z - op2.z;     return result;   }   // Overload unary -.   public static ThreeD operator -(ThreeD op)   {     ThreeD result = new ThreeD();     result.x = -op.x;     result.y = -op.y;     result.z = -op.z;     return result;   }   // Overload unary ++.   public static ThreeD operator ++(ThreeD op)   {     // for ++, modify argument     op.x++;     op.y++;     op.z++;     return op;   }   // Show X, Y, Z coordinates.   public void show()   {     Console.WriteLine(x + ", " + y + ", " + z);   } } class ThreeDDemo {   public static void Main() {     ThreeD a = new ThreeD(1, 2, 3);     ThreeD b = new ThreeD(10, 10, 10);     ThreeD c = new ThreeD();     Console.Write("Here is a: ");     a.show();     Console.WriteLine();     Console.Write("Here is b: ");     b.show();     Console.WriteLine();     c = a + b; // add a and b together     Console.Write("Result of a + b: ");     c.show();     Console.WriteLine();     c = a + b + c; // add a, b, and c together     Console.Write("Result of a + b + c: ");     c.show();     Console.WriteLine();     c = c - a; // subtract a     Console.Write("Result of c - a: ");     c.show();     Console.WriteLine();     c = c - b; // subtract b     Console.Write("Result of c - b: ");     c.show();     Console.WriteLine();     c = -a; // assign -a to c     Console.Write("Result of -a: ");     c.show();     Console.WriteLine();     a++; // increment a     Console.Write("Result of a++: ");     a.show();   } }

The output from the program is shown here:

 Here is a: 1, 2, 3 Here is b: 10, 10, 10 Result of a + b: 11, 12, 13 Result of a + b + c: 22, 24, 26 Result of c - a: 21, 22, 23 Result of c - b: 11, 12, 13 Result of -a: -1, -2, -3 Result of a++: 2, 3, 4

As you know, the ++ and have both a prefix and a postfix form. For example, both

 ++O;

and

 O++;

are valid uses of the increment operator. However, when overloading the ++ or , both forms call the same method. Thus, when overloading, there is no way to distinguish between a prefix or postfix form of ++ or .




C# 2.0(c) The Complete Reference
C# 2.0: The Complete Reference (Complete Reference Series)
ISBN: 0072262095
EAN: 2147483647
Year: 2006
Pages: 300

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net