Microsoft.NET

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

Relational Operator Overloading in C# (OOP’s) – Part 18

Posted by Ravi Varma Thumati on July 13, 2009

C# Relational Operator Overloading

The relational operators allow two values or objects to be compared and a determination made as to whether they are equal or whether one is greater or smaller than the other. There are six relational operators that can be directly overloaded for a class.

These are the equality (==) and inequality (! =) operators, greater than (>), less than (<), greater than or equal to (>=) and less than or equal to (<=).

The six operators should be considered as three linked pairs. When one of any of the three pairs is overloaded, the opposing version must also be overloaded to enable the class to be compiled without error.

Overloading the Equality and Inequality Operators

The equality and inequality operators are binary operators and, as such, are overridden using the same syntax as other basic binary operators. The following syntax is for the equality operator:

public static result-type operator ==(

op-type operand,

op-type2 operand2

)

The result-type is the data type for the return value of the operation. In most cases the result will be a Boolean value. A different return type may be used but this will limit the operator’s functionality. At least one of the two operands must be of the same data type as the containing class. By changing the data type of one of the operands, multiple overloaded versions of the operator can be created and used for comparing objects of different types.

Functional Impact

Overloading the equality operator fundamentally changes the manner in which objects are compared. Under normal circumstances, a comparison of two objects using the equality operator yields a true result only if the two variables being compared are references to the same object. ie. The two object references point to the same area in memory. This can be demonstrated using instances of the Vector class and the VectorDemo project’s Main method as shown in the following example. Note that though vectors v1 and v2 are the same in value, they are not deemed equal.

static void Main(string[] args)

{

Vector v1 = new Vector(3, 4);

Vector v2 = new Vector(3, 4);

Vector v3 = v2;

Console.WriteLine(v2 == v1);                // Outputs “False”

Console.WriteLine(v3 == v2);                // Outputs “True”

}

When you overload the equality operator you can change the comparison from being a direct test that the two object references are the same to being a test that the objects are functionally the same in value. This concept is used by the .NET framework’s provision of string objects. For strings, the equality operator is overloaded so that a comparison of the two strings’ values, rather than their object pointers, is made.

Overloading Equality and Inequality Operators in the Vector Class

Using the syntax described above we can add overloaded equality and inequality operators to the Vector class. The operations will check that both the X and Y co-ordinates of the two Vectors being compared match before deeming the objects to be equal. To overload the two operators, add the following code to the Vector class:

public static bool operator ==(Vector v1, Vector v2)

{

return (v1.X == v2.X && v1.Y == v2.Y);

}

public static bool operator !=(Vector v1, Vector v2)

{

return (v1.X != v2.X || v1.Y != v2.Y);

}

These modifications change the comparisons so that the previous Main method’s results are different. Execute the program again to see that the equality operator now compares the values in the Vector rather than the object references. Note that the v1 and v2 vectors are now considered equal.

static void Main(string[] args)

{

Vector v1 = new Vector(3, 4);

Vector v2 = new Vector(3, 4);

Vector v3 = v2;

Console.WriteLine(v2 == v1);                // Outputs “True”

Console.WriteLine(v3 == v2);                // Outputs “True”

}

The Equals Method

Every class automatically inherits the Equals method. This method performs a comparison of two values or objects, returning a Boolean value indicating if the two items match. For reference type objects such as the Vector class, the comparison is of the two object references. Once the equality operator has been overloaded, the results of == and the Equals method is no longer the same:

static void Main(string[] args)

{

Vector v1 = new Vector(3, 4);

Vector v2 = new Vector(3, 4);

Vector v3 = v2;

Console.WriteLine(v2 == v1);                // Outputs “True”

Console.WriteLine(v3 == v2);                // Outputs “True”

Console.WriteLine(v2.Equals(v1));           // Outputs “False”

Console.WriteLine(v3.Equals(v2));           // Outputs “True”

}

Generally you will want to modify the functionality of the Equals method to match that of the equality operator. This is achieved by overriding the method; a technique that will be described in a later article in this tutorial. After changing the Equals method, a test that the references for two objects match can still is made using the static ReferenceEquals method.

The GetHashCode Method

The GetHashCode method is another member that must be considered when overloading the equality operator for a class. This method uses a hashing algorithm to generate an integer hash code for an object. The hash code generated can be used for many purposes including within a Hashtable collection.

The default implementation for the GetHashCode method generates a hash code value that can be different for two functionally equivalent objects. As with the Equals method, it is usual that when overloading the equality operator you will want to override the GetHashCode method. The hash codes produced can then be based upon the value of the underlying object rather than the object reference.

NB: Warning messages are produced by the compiler when the equality operator is overloaded but the Equals and GetHashCode methods are not overridden. These warnings should not be ignored but will not prevent the code from being compiled or executed.

Overloading the Comparison Operators

The comparison operators are overloaded using the same basic syntax as the equality operator. Again, the operators must be overloaded in pairs. ie, if < is overloaded then so must be > and if <= is overloaded >= must be also.

Overloading the Comparison Operators in the Vector Class

To determine which of two Vector objects is the larger or smaller, the lengths of the two vectors will be compared. To simplify this, we will first add a new, read-only property to the Vector class. This property will use the Pythagorean theorem to calculate the length of the vector.

Add the new property to the Vector class as follows. This code uses the System.Math library for mathematical functions so ensure that the start of the code file includes a using System; statement.

public double Length

{

get

{

return Math.Sqrt(_x * _x + _y * _y);

}

}

Now that we have a Length property to facilitate comparison of Vectors, we can define the four remaining relational operators. Each of the operators will perform a comparison of the lengths of the two vectors passed as operands and return a Boolean result. Add the following code to the Vector class to overload the operators:

public static bool operator >(Vector v1, Vector v2)

{

return (v1.Length > v2.Length);

}

public static bool operator <(Vector v1, Vector v2)

{

return (v1.Length < v2.Length);

}

public static bool operator >=(Vector v1, Vector v2)

{

return (v1.Length >= v2.Length);

}

public static bool operator <=(Vector v1, Vector v2)

{

return (v1.Length <= v2.Length);

}

You can now test the new operators by adjusting the Main method of the program as follows:

static void Main(string[] args)

{

Vector v1 = new Vector(3, 4);

Vector v2 = new Vector(4, 3);

Vector v3 = new Vector(3, 5);

Console.WriteLine(v1 > v2);                 // Outputs “False”

Console.WriteLine(v1 < v2);                 // Outputs “False”

Console.WriteLine(v1 >= v2);                // Outputs “True”

Console.WriteLine(v1 <= v2);                // Outputs “True”

Console.WriteLine(v1 > v3);                 // Outputs “False”

Console.WriteLine(v1 < v3);                 // Outputs “True”

Console.WriteLine(v1 >= v3);                // Outputs “False”

Console.WriteLine(v1 <= v3);                // Outputs “True”

}

Advertisements

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: