10.13 Operator Overloading; Introducing struct

Method-call notation can be cumbersome for certain kinds of operations, such as arithmetic. In these cases, it would be convenient to use C#’s rich set of built-in operators instead. This section shows how to create operators that work with objects of your own types—via a process called operator overloading.

You can overload most operators. Some are overloaded more frequently than others, especially the arithmetic operators, such as + and -, where operator notation is more natural than calling methods. For a list of overloadable operators, see


https://msdn.microsoft.com/library/8edha89s

10.13.1 Creating Value Types with struct

To demonstrate operator overloading, we’ll define type ComplexNumber (Section 10.13.2). Complex numbers have the form


realPart + imaginaryPart * i

where i is 1. Like integers and floating-point numbers, complex numbers are arithmetic types that are commonly used in calculations. As you know, C#’s simple numeric types are value types. To mimic the simple numeric types, we’ll define ComplexNumber as a value type by using a struct (short for “structure”) rather than a class. C#’s simple types like int and double are actually aliases for struct types—an int is defined by the struct System.Int32, a long by System.Int64, a double by System.Double and so on. The operator overloading techniques shown in Section 10.13.2 also can be applied to classes.

When to Declare a struct Type

Microsoft recommends using classes for most new types, but recommends a struct if:

  • the type represents a single value—a complex number represents one number that happens to have a real part and an imaginary part.

  • the size of an object is 16 bytes or smaller—we’ll represent a complex number’s real and imaginary parts using two doubles (a total of 16 bytes).

For the complete list of struct recommendations, see


https://msdn.microsoft.com/library/ms229017

10.13.2 Value Type ComplexNumber

Value type ComplexNumber (Fig. 10.14) overloads the plus (+), minus (-) and multiplication (*) operators to enable programs to add, subtract and multiply instances of class ComplexNumber using common mathematical notation. Lines 9–10 define getter-only auto-implemented properties for the ComplexNumber’s Real and Imaginary components.

Fig. 10.14 Value type that overloads operators for adding, subtracting and multiplying complex numbers.

Alternate View

 1    // Fig. 10.14: ComplexNumber.cs
 2    // Value type that overloads operators for adding, subtracting
 3    // and multiplying complex numbers.
 4    using System;
 5
 6    public struct ComplexNumber
 7    {
 8       // read-only properties that get the real and imaginary components
 9       public double Real { get; }
10       public double Imaginary { get; }
11
12       // constructor
13       public ComplexNumber(double real, double imaginary)
14       {
15       Real = real;
16       Imaginary = imaginary;
17      }
18
19       // return string representation of ComplexNumber
20       public override string ToString() =>
21          $"({Real} {(Imaginary < 0 ? "-" : "+")} {Math.Abs(Imaginary)}i)";
22
23       // overload the addition operator
24       public static ComplexNumber operator+(ComplexNumber x, ComplexNumber y)
25       {
26          return new ComplexNumber(x.Real + y.Real,
27             x.Imaginary + y.Imaginary);
28       }
29
30       // overload the subtraction operator
31       public static ComplexNumber operator-(ComplexNumber x, ComplexNumber y)
32       {
33          return new ComplexNumber(x.Real - y.Real,
34              x.Imaginary - y.Imaginary );
35       }
36
37        // overload the multiplication operator
38        public static ComplexNumber operator*(ComplexNumber x, ComplexNumber y)
39       {
40           return new ComplexNumber(
41              x.Real * y.Real - x.Imaginary * y.Imaginary,
42              x.Real * y.Imaginary + y.Real * x.Imaginary);
43        }
44     }

Constructor

Lines 13–17 define a ComplexNumber constructor that receives parameters to initialize the Real and Imaginary properties. Unlike a class, you cannot define a parameterless constructor for a struct—the compiler always provides a default constructor that initializes the struct’s instance variables to their default values. Also, structs cannot specify initial values in instance variable or property declarations.

Overloaded Operators

Lines 24–28 overload the plus operator (+) to add ComplexNumbers. Keyword operator, followed by an operator symbol (such as +), indicates that a method overloads the specified operator. Overloaded operator methods are required to be public and static.

Methods that overload binary operators must take two arguments—the first is the left operand and the second is the right operand. Class ComplexNumber’s overloaded + operator takes two ComplexNumbers as arguments and returns a ComplexNumber that represents the sum of the arguments. The method’s body adds the ComplexNumbers and returns the result as a new ComplexNumber.

We do not modify the contents of either of the original operands passed as arguments x and y. This matches our intuitive sense of how this operator should behave—adding two numbers does not modify either of the original values. Lines 31–43 declare similar overloaded operators to subtract and multiply ComplexNumbers.

Software Engineering Observation 10.15

Overload operators to perform the same function or similar functions on objects as the operators perform on objects of simple types. Avoid nonintuitive use of operators.

 

Software Engineering Observation 10.16

At least one parameter of an overloaded operator method must be of the type in which the operator is overloaded. This prevents you from changing how operators work on simple types.

 

Software Engineering Observation 10.17

Though you cannot overload the arithmetic assignment operators (e.g., += and -=), C# allows you to use them with any type that declares the corresponding arithmetic operator (e.g., + and -).

10.13.3 Class ComplexTest

Class ComplexTest (Fig. 10.15) demonstrates the overloaded ComplexNumber operators +, - and *. Lines 10–21 prompt the user to enter the real and imaginary parts of two complex numbers, then use this input to create two ComplexNumber objects for use in calculations.

Fig. 10.15 Overloading operators for complex numbers.

Alternate View

 1    // Fig. 10.15: ComplexTest.cs
 2    // Overloading operators for complex numbers.
 3    using System;
 4
 5    class ComplexTest
 6    {
 7       static void Main()
 8       {
 9           // prompt the user to enter the first complex number
10           Console.Write("Enter the real part of complex number x: ");
11           double realPart = double.Parse(Console.ReadLine());
12           Console.Write("Enter the imaginary part of complex number x: ");
13           double imaginaryPart = double.Parse(Console.ReadLine());
14           var x = new ComplexNumber(realPart, imaginaryPart);
15
16           // prompt the user to enter the second complex number
17           Console.Write("
Enter the real part of complex number y: ");
18           realPart = double.Parse(Console.ReadLine());
19           Console.Write("Enter the imaginary part of complex number y: ");
20           imaginaryPart = double.Parse(Console.ReadLine());
21           var y = new ComplexNumber(realPart, imaginaryPart);
22
23           // display the results of calculations with x and y
24           Console.WriteLine();
25           Console.WriteLine($"{x} + {y} = {x + y}");
26           Console.WriteLine($"{x} - {y} = {x - y}");
27           Console.WriteLine($"{x} * {y} = {x * y}");
28        }
29     }

Enter the real part of complex number x: 2
Enter the imaginary part of complex number x: 4

Enter the real part of complex number y: 4
Enter the imaginary part of complex number y: -2

(2 + 4i) + (4 - 2i) = (6 + 2i)
(2 + 4i) - (4 - 2i) = (-2 + 6i)
(2 + 4i) * (4 - 2i) = (16 + 12i)

Lines 25–27 add, subtract and multiply x and y with the overloaded operators (in string-interpolation expressions), then output the results. In line 25, we use the + operator with ComplexNumber operands x and y. Without operator overloading, the expression x + y wouldn’t make sense—the compiler wouldn’t know how to add two ComplexNumber objects. This expression makes sense here because we’ve defined the + operator for two ComplexNumbers in lines 24–28 of Fig. 10.14. When the two ComplexNumbers are “added” in line 25 of Fig. 10.15, this invokes the operator+ declaration, passing the left operand as the first argument and the right operand as the second argument. When we use the subtraction and multiplication operators in lines 26–27, their respective overloaded operator declarations are invoked similarly.

Each calculation’s result is the new ComplexNumber object returned by the corresponding overloaded operator method. When this new object is placed in a string-interpolation expression, its ToString method (Fig. 10.14, lines 20–21) is implicitly invoked. The expression x + y in line 25 of Fig. 10.15 could be rewritten to explicitly invoke the ToString method of the resulting ComplexNumber object, as in:


(x + y).ToString()
..................Content has been hidden....................

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