Microsoft & .NETVisual C#Overloading Operators in C#

Overloading Operators in C#

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Welcome to the next installment of the .NET Nuts & Bolts column. With the release of the Microsoft .NET framework, Microsoft introduced many new concepts to some of their programming languages. One of these concepts, included with C# but not VB.NET, is the ability to overload operators. In this column we’ll explore operators using C#.

Operators

Operator overloading, also known as overloading, provides a way to define and use operators such as +, -, and / for user-defined classes or structs. It allows us to define/redefine the way operators work with our classes and structs. This allows programmers to make their custom types look and feel like simple types such as int and string. It consists of nothing more than a method declared by the keyword operator and followed by an operator. There are three types of overloadable operators called unary, binary, and conversion. Not all operators of each type can be overloaded. We will cover each type of operator in more detail below.

Overloading Unary Operators

Unary operators are those that require only a single operand/parameter for the operation. The class or struct involved in the operation must contain the operator declaration. They include +, -, !, ~, ++, –, true, and false. When overloading unary operators, the following rules apply:

  • +, -, !, or ~ must take a parameter of the defining type and can return any type
  • ++ or – must take and return the defining type
  • true or false must take a parameter of the defining type and can return a bool

Overloading Unary Operator Sample Code

The following example contains a simple class representing a counter.

using System;namespace CodeGuru.Operators{  /// <remarks>  /// Class that implements a simple counter.  /// </remarks>  public class MyCounter    {      private int _CounterValue = 0;      /// <value>Get or set the counter value</value>      public int CounterValue    {      get { return this._CounterValue; }      set { this._CounterValue = value; }    }    /// <summary>    /// Constructor    /// </summary>    /// <param name="InitialValue">Initial counter value</param>    public MyCounter(int InitialValue)    {      this.CounterValue = InitialValue;    }    /// <summary>    /// Increment the counter by one.    /// </summary>    /// <param name="Counter">Counter to increment</param>    /// <returns>Incremented counter</returns>    public static MyCounter operator ++(MyCounter Counter)    {      Counter.CounterValue++;      return Counter;    }    /// <summary>    /// Decrement the counter by one.    /// </summary>    /// <param name="Counter">Counter to decrement</param>    /// <returns>Decremented counter</returns>    public static MyCounter operator --(MyCounter Counter)    {      Counter.CounterValue--;      return Counter;    }  }}

The following code demonstrates using the above sample code.

MyCounter count = new MyCounter(5);count++;

Overloading Binary Operators

Binary operators are those that require two operands/parameters for the operation. One of the parameters has to be of a type in which the operator is declared. They include +, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, and <=.

Overloading Binary Operator Sample Code

The following example demonstrates the implementation of the > and < operators on a class that represents a standardized test score. The score of such tests is generally comprised of the combination of scores from various sections. The operator overloading allows us to compare test score sets without having to examine the scores from individual sections of the test.

using System;namespace CodeGuru.Operators{  /// <remarks>  /// Class representing a standardized test whose score is  /// comprised  /// of the scores from various sections.  /// </remarks>  public class StandardizedTest  {    private int _MathScore = 0;    /// <value>Get or set the math score</value>    public int MathScore    {      get { return this._MathScore; }      set { this._MathScore = value; }  }    private int _Reading = 0;    /// <value>Get or set the reading score</value>    public int Reading    {      get { return this._Reading; }      set { this._Reading = value; }    }    private int _Science = 0;    /// <value>Get or set the science score</value>    public int Science    {      get { return this._Science; }      set { this._Science = value; }    }    /// <summary>    /// Constructor    /// </summary>    /// <param name="math">Math score</param>    /// <param name="reading">Reading score</param>    /// <param name="science">Science score</param>    public StandardizedTest(int math, int reading, int science)    {      this.MathScore = math;      this.Reading = reading;      this.Science = science;    }    /// <summary>    /// Determine if the first test score is greater.    /// </summary>    /// <param name="score1"></param>    /// <param name="test2"></param>    /// <returns></returns>    public static bool operator >(StandardizedTest score1,                                  StandardizedTest score2)    {      if( (score1.MathScore + score1.Reading + score1.Science) >          (score2.MathScore + score2.Reading + score2.Science) )    {      return true;    }      return false;    }    /// <summary>    /// Determine if the first test score is less.    /// </summary>    /// <param name="score1"></param>    /// <param name="test2"></param>    /// <returns></returns>    public static bool operator <(StandardizedTest score1,                                  StandardizedTest score2)    {      if( (score1.MathScore + score1.Reading + score1.Science) <          (score2.MathScore + score2.Reading + score2.Science) )      {        return true;      }      return false;    }  }}

The following code demonstrates using the above sample code to compare two test score sets to determine whether score1 is higher than score2.

StandardizedTest test1 = new StandardizedTest(200,400,400);StandardizedTest test2 = new StandardizedTest(400,400,400);if( test1 > test2 ){  Console.WriteLine("Student1 performed better");}else{  Console.WriteLine("Student1 did not do better");}

Overloading Conversion Operators

Conversion operators are those that involve converting from one data type to another through assignment. There are implicit and explicit conversions. Implicit conversions are those that involve direct assignment of one type to another. Explicit conversions are conversions that require one type to be casted as another type in order to perform the conversion. Conversions that may cause exceptions or result in loss of data as the type is converted should be handled as explicit conversions.

Overloading Implicit Conversion Operator Sample Code

The following example demonstrates a custom class that represents different formats of files that can be transferred to an application. Creating an implicit conversion of type string allows us to assign string values to an object of type FileFormat without requiring we use the member properties. This is particularly useful if you were going to read a value from a database and assign it to an object.

using System;namespace CodeGuru.Operators{  /// <remarks>  /// File formats may be comma delimited, positional, or XML.  /// </remarks>  public class FileFormat  {    public const String COMMA_DELIMITED = "C";    public const String POSITIONAL = "P";    public const String XML = "X";    private string _FileFormatValue;    /// <value>Get or set the file format value</value>    public string FileFormatValue    {      get { return this._FileFormatValue; }      set      {        if( value.Equals(FileFormat.COMMA_DELIMITED) ||            value.Equals(FileFormat.POSITIONAL) ||            value.Equals(FileFormat.XML) )        {          this._FileFormatValue = value;        }      }    }    /// <summary>    /// Constructor    /// </summary>    public FileFormat()    {      this._FileFormatValue = "";    }    /// <summary>    /// Implicitly convert from a string to FileFormat.    /// </summary>    /// <param name="v_Value">Value to convert</param>    /// <returns>FileFormat</returns>    public static implicit operator          FileFormat(System.String v_Value)    {      FileFormat f = new FileFormat();      f.FileFormatValue = v_Value;      return f;    }  }}

The following code demonstrates using the above sample code.

string dbFileType = "C";    // Assume this is from a databaseFileType fileType = new FileType();fileType = dbFileType;

Overloading Explicit Conversion Operator Sample Code

The above example can be turned into an explicit operator by changing the “implicit” keyword to “explicit” on the operator definition. The assignment would then require the string to be casted as a FileType as following example demonstrates.

string dbFileType = "C";    // Assume this is from a databaseFileType fileType = new FileType();fileType = (FileType)dbFileType;

Summary

We have explored the different ways in which operators may be overloaded within C#. There are numerous ways that overloading can be used to your advantage in custom classes and structs. It is now up to you to decide how to best put it to use in your applications, and important to remember that not all languages support operator overloading.

Future Columns

The topic of the next column is yet to be determined. If you have something in particular that you would like to see explained here you could reach me at mstrawmyer@crowechizek.com.

About the Author

Mark Strawmyer, MCSD, MCSE, MCDBA is a Senior Architect of .NET applications for large and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in architecture, design, and development of Microsoft-based solutions. You can reach Mark at mstrawmyer@crowechizek.com.

# # #

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories