Sunday, November 14, 2010

C# - Overloading cast operator, Implicit conversion and explicit conversion overloading

What is Operator Overloading?


We know that standard data types supplied by languages are well known and there will be operators like <code>+,* ,%</code> operates on these data types.  But, what is the case if it is user-defined types say a 3dpoint class, which is the combination of three integers. Well, all languages that supports operator overloading says, “It is you Type. Please you say how the operator + should work”.

If you say “How the Operator + should work for 3point class”, then the your overloading + operator. Because, it will now know how add two integer and how to add two 3dpoint.

Below are the types of overloading that I will demonstrate in this article:
1) Implicit Conversion Operator
2) Explicit Conversion Operator
3) Binary Operator


Let us start with TimeHHMMSS class


Before we move on to the Overloading, first let me explain what this class will do. The class is used to store the time in Hour, Minute and Seconds. There are three members defined for that. The class Looks Like:
class TimeHHMMSS
{
      //001: Parts of the time class
      public int m_hour;
      public int m_minute;
      public int m_sec;



The default constructor will set all the members to zero. And a overloaded version will accept hour, minute and Seconds. Below is the code for Constructors:
//002: Default constructor for the class
public TimeHHMMSS()
{
      m_hour = 0;
      m_minute = 0;
      m_sec = 0;
}
//003: Overloaded Constructor
public TimeHHMMSS(int hr, int min, int sec)
{
      m_hour = hr;
      m_minute = min;
      m_sec = sec;
}

All classes in C# have Object as their base class. We will override the ToString method our own way.
//004: Every class that we create has Object as the base class. Override the ToString
public override string ToString()
{
      return string.Format("{0}:{1}:{2}", m_hour, m_minute, m_sec);
}


Implicit Conversion – (A) Integer to TimeHHMMSS


Below is the Syntax for Implicit conversion:
public static implicit operator <Convert to> (<ConvertFrom> Variable)

We will get the integer as parameter. So the time is specified in smaller units say in seconds passed as an integer parameter. 1 Hour, 10 minutes, 15 Seconds can be specified in seconds as 4215. These “seconds” taken as an integer parameter is processed to split into Hour,Minutes,and Seconds. After the Split, we have all the member variable of the class is ready to return back. Below is the Conversion operator:

//005: Implicit Conversion Operator. Coversion from int to TimeHHMMSS
public static implicit operator TimeHHMMSS(int totalSeconds)
{    
      //005_1 : Declarations
      int hour, min, seconds;
      int RemainingSeconds;
      TimeHHMMSS returnobject = new TimeHHMMSS();

      //005_2: Calculate Seconds
      seconds = totalSeconds % 60;
      returnobject.m_sec = seconds;

      //005_3: Calculate Minutes
      RemainingSeconds = totalSeconds - seconds;
      min = RemainingSeconds % ( 60 * 60 ); //Calculated minutes in terms of seconds
      returnobject.m_minute = min / 60 ;

      //005_4: Calculate Hours
          RemainingSeconds =  totalSeconds - ( returnobject.m_minute * 60 + returnobject.m_sec );
      hour = RemainingSeconds % (60 * 60 * 24 ); // Hour in Seconds
      returnobject.m_hour = hour / 3600;

      return returnobject;
}

OK, how the above operator is used? If we assume t2 is the TimeHHMMSS object constructed using the default constructor the below statement will invoke the implicit conversion overloaded
t2 = 33175;

Implicit Conversion – (B) TimeHHMMSS to Integer


Now, we will implement the same implicit conversion in the reverse; that is, we will make conversion from Time Object to integer. I hope as looked at the previous function, you will know what the implementation is. Below is the function:

//006: Implicit Conversion Operator. Conversion from TimeHHMMSS to integer
public static implicit operator int(TimeHHMMSS time)
{
      return (time.m_hour * 60 * 60) + (time.m_minute * 60 ) + time.m_sec ;
}

When will the calling code invoke the above implicit conversion? The code is below:
int timeinSeconds;
timeinSeconds = t2;

Explicit Conversion- Conversion from Float to TimeHHMMSS

In the above conversion we saw that the conversion takes place even we do not explicitly specify that. The way we implement the Time class is we recommend integer data type, so we make the conversion for integer implicit. For a float data type we will implement (Not actually an implementation, we will handle if a user accidentally make an float conversion explicitly, and re-direct to int implicit conversion).

Below is the code that will take a float, re-directs to integer implicit conversion. From the client point of view it is an explicit conversion:

//007: Explicit Conversion Operator. Conversion from float to TimeHHMMSS.
public static explicit operator TimeHHMMSS(float totalSeconds) // We don't want to handle fraction in Seconds (Micro Sec or nano Sec stc)
{
      TimeHHMMSS returnobject = new TimeHHMMSS();
      returnobject = (int) totalSeconds; //Makes a call to implicit convertion : int->TimeHHMMSS
      return returnobject;
}

Below is the piece of client code, which will make a call to our explicit overloaded operator:
TimeHHMMSS t3 = (TimeHHMMSS) 23213.67f;

Binary Operator Overloading – Overload + operator


Now, it is time to overload the binary operator +. With this we can add two TimeHHMMSS class and get back the added TimeHHMMSS.

The called will write statement something like the one below:
TimeHHMMSS t4 = t1 + t2;

Our + overloading function will take TimeHHMMSS t1,t2 as two parameters in the same order; that is t1 as first parameter and t2 as second parameter. Then, the added TimeHHMMSS is returned back to the t4 object of the same type.

We will use the implicit Time->Integer conversion on t1 and t2.  Add the integer values then return the added value. Since, the return type we specify as TimeHHMMSS, Once again an implicit conversion in reverse direction takes place; that a conversion from integer->TimeHHMMSS. The overloaded + operator is shown below:

//008: Operator Overloading +. Binary Operator.
public static TimeHHMMSS operator+ (TimeHHMMSS operandLH, TimeHHMMSS OperandRH)
{
      //008_1: Get the Seconds and Add.
      int totalSeconds, LHS_Seconds, RHS_Seconds;
      LHS_Seconds = operandLH;        //Implicit convertion: Time -> int
      RHS_Seconds = OperandRH;        //Implicit convertion: Time -> int
      totalSeconds = LHS_Seconds + RHS_Seconds;

      //008_2:    Return the Seconds. Required return type is TimeHHMMSS,
      //                what we return is integer. Again one more implicit conevrtion in reverse
      return totalSeconds; //Implicit convertion: int -> Time
}


Closing Notes:

1) The binary operator will work for the following statements also:
t4 = t4 + 4215;
t4 = t4 + (TimeHHMMSS) 54321.456f ;
Debug to see what kind of conversion takes place.

2) If you overload an == operator, then you should overload !=. Same holds for operator like < and >. Etc

Hope you like this article.


Source Code: Download Here

1 comment:

Leave your comment(s) here.

Like this site? Tell it to your Firend :)