Microsoft.NET

……………………………………………….Expertise in .NET Technologies

Basic Operator Overloading in C# (OOP’s) – Part 16

Posted by Ravi Varma Thumati on July 13, 2009

C# Basic Operator Overloading

So far in this tutorial we have created classes to represent real-world objects complete with their appropriate methods and properties. These objects have not required the implementation of arithmetic operators as this type of functionality was not appropriate. In this article, we will create a class that does support arithmetic operations through the use of operator overloading.

Operator overloading is simply the process of adding operator functionality to a class. This allows you to define exactly how the operator behaves when used with your class and other data types. This can be standard uses such as the ability to add the values of two vectors, more complex mathematics for multiplying matrices or non-arithmetic functions such as using the + operator to add a new item to a collection or combine the contents of two arrays. Multiple overloaded versions of operators may also be created to provide different functionality according to the data types being processed, in a similar manner to the varying signatures of method overloading.

In this session we will create a new class to represent a two-dimensional vector with X and Y properties. We will use this class in this article and future articles to demonstrate operator overloading. To start, create a new console application named “VectorDemo” and add a new class file named “Vector”. Add the following code to the new class to create the properties and a basic constructor:

private int _x, _y;

public Vector(int x, int y) { _x = x; _y = y; }

public int X

{

get { return _x; }

set { _x = value; }

}

public int Y

{

get { return _y; }

set { _y = value; }

}

Binary Operator Overloading

The first type of operator to consider is the binary operator, so named because they require two values to work with. These include the simple arithmetic operators such as +, -, *, / and %. To declare a binary operator, the following syntax is used:

public static result-type operator binary-operator (

op-type operand,

op-type2 operand2

)

This initially appears to be a rather complex declaration but in fact is quite simple. The declaration starts with public static as all operators must be declared as such. Other scopes are not permitted and neither are non-static operators.

The result-type defines the data type or class that is returned as the result of using the operator. Usually this will be the same type as the class that it is being defined within. However, that need not be the case and it is perfectly valid to return data of a different type.

The operator keyword is added to tell the compiler that the following binary-operator symbol is an operator rather than a normal method. This operator will then process the two operand parameters, each prefixed with its data type (op-type and op-type2). As least one of these operands must be the same type as the containing class.

Creating the Addition (+) Operator

The syntax for binary operators can now be used to create a new addition operator for the Vector class. This operator will simply add the X and Y elements of two vectors together and return a new vector containing the result. Add the following to the Vector class to provide this functionality. Note that a new Vector is created rather than adjusting one of the operands. This is because the operands are reference-types and the original values should not be updated in this case.

public static Vector operator +(Vector v1, Vector v2)

{

return new Vector(v1.X + v2.X, v1.Y + v2.Y);

}

We can now test the Vector’s new operator by modifying the program’s main method. The following program instantiates two Vector objects, adds them together and outputs the values of the resultant Vector’s X and Y properties.

static void Main(string[] args)

{

Vector v1 = new Vector(4, 11);

Vector v2 = new Vector(0, 8);

Vector v3 = v1 + v2;

Console.WriteLine(“({0},{1})”, v3.X, v3.Y);     // Outputs “(4,19)”

}

Creating the Subtraction (-) Operator

Addition is a commutative operation. This means the order of the two operands can be swapped without affecting the outcome. In the case of subtraction this is not the case so it important to remember that the first operand in the declaration represents the value to the left of the operator and the second operand represents the value to the right. If these are used incorrectly, the resultant value will be incorrect. Using this knowledge we can add a subtraction operator to the Vector class:

public static Vector operator -(Vector v1, Vector v2)

{

return new Vector(v1.X – v2.X, v1.Y – v2.Y);

}

To test the new operator, modify the Main method as follows and execute the program.

static void Main(string[] args)

{

Vector v1 = new Vector(4, 11);

Vector v2 = new Vector(0, 8);

Vector v3 = v1 – v2;

Console.WriteLine(“({0},{1})”, v3.X, v3.Y);     // Outputs “(4,3)”

}

Creating the Multiplication (*) Operator

The last binary operator that will be added to Vector class is for multiplication. This operator will be used to scale the vector by multiplying the X and Y properties by the same integer value. This demonstrates the use of operands of a different type to the class they are defined within.

public static Vector operator *(Vector v1, int scale)

{

return new Vector(v1.X * scale, v1.Y * scale);

}

To test the multiplication operator, adjust the Main method again:

static void Main(string[] args)

{

Vector v1 = new Vector(4, 11);

Vector v2 = v1 * 3;

Console.WriteLine(“({0},{1})”, v2.X, v2.Y);     // Outputs “(12,33)”

}

In the operator code for the multiplication operator, the Vector is the first operand and the integer the second. This means that the order used in the multiplication statement must have the Vector at the left of the operator and the integer value to the right. Changing the order of the operands in the Main method will cause a compiler error.

static void Main(string[] args)

{

Vector v1 = new Vector(4, 11);

Vector v2 = 3 * v1;

Console.WriteLine(“({0},{1})”, v2.X, v2.Y);     // Does not compile

}

If the class must support both variations of multiplication, both must be declared in the code. This provides the benefit of allowing the order of operands change the underlying function. To provide the second variation of multiplication, add the following code to the Vector class. Afterwards, the program will execute correctly.

public static Vector operator *(int scale, Vector v1)

{

return new Vector(v1.X * scale, v1.Y * scale);

}

Compound Assignment Operators

When an arithmetic binary operator is declared, the corresponding compound assignment operator is also made available to the class. This can be demonstrated by modifying the Main method of the program:

Vector v1 = new Vector(4, 11);

v1 *= 5;

Console.WriteLine(“({0},{1})”, v1.X, v1.Y);         // Outputs “(20,55)”

Unary Operator Overloading

Unary operators are those that require a single operand. These include the simple increment (++) and decrement (–) operators. To declare a unary operator, the following syntax is used:

public static result-type operator unary-operator (op-type operand)

This syntax is almost identical to that used for binary operators. The difference is that only one operand is declared. The operand type must be the same as the class in which the operator is declared.

Creating the Increment and Decrement Operators

Using the syntax defined above, we can now add the increment and decrement operators to the Vector class. Note that there is only a single definition for each. There is no way to differentiate between prefix and postfix versions of the operator so both provide the same underlying functionality.

To declare the two operators, add the following code to the Vector class. Each increments or decrements both the X and Y properties for Vector objects.

public static Vector operator ++(Vector v)

{

v.X++;

v.Y++;

return v;

}

public static Vector operator –(Vector v)

{

v.X–;

v.Y–;

return v;

}

To test these operators, update and execute the Main method:

static void Main(string[] args)

{

Vector v1 = new Vector(4, 11);

v1++;

Console.WriteLine(“({0},{1})”, v1.X, v1.Y);     // Outputs “(5,12)”

v1–;

Console.WriteLine(“({0},{1})”, v1.X, v1.Y);     // Outputs “(4,11)”

}

Creating the Negation Operator

The last arithmetic unary operator to be considered in this article is the negation operator. This is the unary version of subtraction used to identify a negative version of a value. We can add this operator using the following code:

public static Vector operator -(Vector v)

{

return new Vector(-v.X, -v.Y);

}

To test the negation operator, update the Main method and run the program.

static void Main(string[] args)

{

Vector v1 = new Vector(4, 11);

Vector v2 = -v1;

Console.WriteLine(“({0},{1})”, v2.X, v2.Y);     // Outputs “(-4,-11)”

}

Overloading True and False in C#

The true and false keywords have many uses in C#. One of these uses is as a pair of operators within a class that allow the class to represent its own state as either true or false. The determination of the result is implemented in rules coded by the programmer. This effectively gives an implicit conversion of a type to a Boolean value that can then be used in conditional processing scenarios such as with the If statement or the conditional operator (?).

Adding True and False Operators (Default Behavior)

The default behavior of any class is to provide no support for the true and false operators. This means that if an attempt is made to evaluate an object of such a class as a Boolean the code will fail to compile. This can be demonstrated by using a Vector object as the condition in if statement. Change the Main method of the VectorDemo program as follows and attempt to compile it to see the error.

static void Main(string[] args)

{

Vector test = new Vector(4, 3);

if (test)

Console.WriteLine(“True”);

else

Console.WriteLine(“False”);

}

Overloading True and False

The syntax for overloading the true and false operators is similar to that of other unary operators. Two limitations exist. Firstly, the return value must be a Boolean. Secondly, it is invalid to overload only one of the two operators; if the true operator is overloaded than so must be false and vice versa.

public static bool operator true(op-type operand)

{

// Evaluation code

}

public static bool operator false(op-type operand)

{

// Evaluation code

}

Adding True and False to the Vector Class

The Vector class can now be updated to include overloaded versions of the true and false operators. In the case of vectors, the object will be deemed to be ‘true’ when either of the vector’s X or Y properties is non-zero. If the X and Y values are both zero, the object will evaluate as false. This is simply implemented by adding the following code:

public static bool operator true(Vector v)

{

if ((v.X != 0) || (v.Y != 0))

return true;

else

return false;

}

public static bool operator false(Vector v)

{

if ((v.X == 0) && (v.Y == 0))

return true;

else

return false;

}

Testing the Code

Now that the two operators have been added, you should be able to compile and execute the Main method described above. As the vector’s X and Y co-ordinates are not zero, the code outputs the text “True”. If you modify the Vector’s declaration as follows, the code will output false instead.

static void Main(string[] args)

{

Vector test = new Vector(0, 0);

if (test)

Console.WriteLine(“True”);

else

Console.WriteLine(“False”);         // Outputs “False”

}

Advertisements

One Response to “Basic Operator Overloading in C# (OOP’s) – Part 16”

  1. That is one of the better posts I have looked over concerning this particular topic, you really know your stuff.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: