Developer

Behavior modification: Overload your C# operators

You can force C#'s operators to act the way you want by overloading them with custom behavior. Here are a couple of examples that will show you how to take advantage of this trick.


C# provides functionality for replacing the default behavior of many of its arithmetic, comparison, and logic operators with behaviors you create. This provides backward compatibility with C++ applications that you may one day want to port to C#. Although it can be confusing to see in action, operator overloading is some nifty syntactic sugar that you can easily use to provide custom arithmetic or comparison operations in your own applications.

In C#, any unary (single operand, such as ++) and binary (two operands, such as ==) operator, with the exceptions of the assignment statement (=) and the bitwise and (&&) and or (||) operators, can be overridden with custom behavior. In the case of comparison operators, you’ll need to provide custom behavior for the reverse operator as well. That is, to override the less-than comparison operator (<), you’ll also have to override the greater-than comparison operator (>). Operator overloads in a base class are inherited by all child classes, which can, in turn, override the base class’s operators with their own implementation.

You declare an operator overload by defining a new operator method for the class or struct that you want to use the new behavior. This new method must always be static: It belongs to the type and not to an instance of the type. The C# operator method prototype takes the following form:
public static type operator op(value_list)

In this format, the type placeholder indicates the type that an expression using the operator will return; op is the operator you want to override; and value_list is a typed list of parameters that will appear in the expression. These parameters will be passed to your implementation in order, from the left to right side of the expression.

Comparing apples and oranges
By way of example, I’ll try to work through an age-old conundrum: the task of comparing apples and oranges. In Listing A, you’ll find the code for three classes, Oranges, Apples, and Fruit. Fruit serves as the base class for both of the former classes and defines custom behavior for the equality (==) and inequality (!=) operators. Looking at the operator that Fruit defines for ==, you can see that it accepts two parameters, also of type Fruit, and compares the size property of each (how else would you compare them?), returning true only if both parameters have the same value for size. Apples and Oranges both implement similar custom behavior for the greater-than and less-than operators.

Oranges, in fact, goes one step further to prove that operator overloads can be overridden. It overrides Fruit’s equality operator behavior with one of its own, sending a special message to the console to show it’s been called.

What we’ve gained here is the ability to write code to compare instances of these two classes. It looks like this:
Oranges o = new Oranges();
Apples a = new Apples();
o.size = 15;
a.size = 20;
 
//compare an apple to an orange
if (o > a) {

}

Listing A will generate warnings
I should tell you that the C# compiler will generate a few warnings when compiling the code in Listing A. That’s because I broke a small rule: When overriding the == or != operator, you should also override the Equals and GetHashCode methods of the base Object class. It’s no crime if you don’t, but you will get inconsistent behavior.

Overloading arithmetic operators
I’ll leave you with a somewhat more practical application of operator overloading involving collections. Suppose you have two collections, c1 and c2, and you want to merge their contents. You could iterate through the contents of c2 and add each item to c1 in turn. But wouldn’t it be more fun (and probably a bit more intuitive) if you could use the following code and be done with it?
c1 = c1 + c2;

If you answered yes, you should definitely check out the OpOverloadCol class in Listing B to see how to overload the addition operator to accomplish just that. When overloading an arithmetic operator like addition, you also implicitly overload the abbreviated assignment operator. In this case, overriding + also lets me use the += operator in the same fashion, as you can see in Listing B.

Taking control
Overloading C# operators facilitates backward compatibility with C++ applications, but you can use the same approach to get extra mileage out of those operators in your C# apps. Overriding the default behavior of an operator provides custom behavior for your classes—almost as if you had a toolbox full of tailor-made operators.

 

 

Editor's Picks

Free Newsletters, In your Inbox