Click here to Skip to main content
15,880,725 members
Articles / Programming Languages / C#

Operator Overloading with Implicit and Explicit Casts in C#

Rate me:
Please Sign up or sign in to vote.
4.15/5 (6 votes)
10 Jul 2010CPOL4 min read 48.7K   4   9
This post demonstrates how easily you can implement a class / structure that may take part in arithmetic operation using Operator overloading of implicit and explicit cast operators

It's been a very common mistake of not declaring implicit and explicit cast operator overloads while working with data types which might take part in some calculations in the long run. I found that many of the developers don't know why we use checked or unchecked while doing calculations. On this regard, I thought of posting an article on how you can use Cast overloads to get your job done easily when you require your type to take part in arithmetic operations and casts to arithmetic data types.

Let us explain the concept using an example. Say I declare a class that would take Feet and inches in one single type. C# doesn't expose such a type to us. So let us create one for us to demonstrate the concept.

C#
public class Finch
    {
        private int feet;
        private int inch;

        public int Feet
        {
            get { return this.feet; }
            set
            {
                this.feet = value;
            }
        }
        public int Inches
        {
            get { return this.inch; }
            set
            {
                if (value > 11)
                {
                    this.feet += (value / 12);
                    this.inch = (value % 12);
                }
                else
                    this.inch = value;
            }
        }
        public override string ToString()
        {
            return string.Format("{0}''{1}'", this.Feet, this.Inches);
        }
    }

So you can see, I have declared a class Finch which has two members Feet and Inches. The class is used to hold. As a matter of fact, the value of inches cannot be made over 11. So in the setter of inches, we strip the values which is greater than 11 to add up to the feet. So that we always get the proper value for Feet and inches.

Let's take the class a bit further.

Operator Overloading

We all might somehow know what operator overloading is. Overloading an operator means extending the nature of a normal operator to make it work little more than what it is capable of doing so. Let's overload the operator + for our class Finch.

C#
public static Finch operator +(Finch oldvalue, dynamic value)
{
    checked
    {
        if (value is Finch)
        {
            Finch newValue = value as Finch;
            oldvalue.Feet += newValue.Feet;
            oldvalue.Inches += newValue.Inches;
            return oldvalue;
        }
        else //try if its a fraction
        {
            decimal d;
            try
            {
                d = Convert.ToDecimal(value); // when conversion fails 
					// it throws exception in runtime
            }
            catch
            {
                throw;
            }
            oldvalue.Feet += Convert.ToInt32(Decimal.Truncate(d));
            var thisval =  Math.Abs(oldvalue.feet - d);
            oldvalue.Inches += (int)(.83f / Convert.ToSingle(thisval));
            return oldvalue;
        }
    }
}

In the above code, you can see that we have overloaded the + operator to take almost everything in compile type, as we defer the check to run time using dynamic keyword. If you are not aware of this, please take a look at my previous article, to clear it up. If you are not in C# 4.0, you can easily replace it with any of the known data types.

You can see that I have wrapped the entire code within a checked block. This will ensure that the block throws OverflowException whenever the conversion produces Arithmetic Overflows. If you don't want this to happen, you can either wrap the checked block into a try-catch block to ensure you handle the OverflowException within it.

As we overload the + operator with dynamic variable, we first check whether the dynamic variable is an object of Finch. If so, we just add up the feet and inches of the new Finch variable.
Otherwise, we check if the value is convertible to a Decimal. This will also ensure that the variable passed within the block can take part in arithmetic operations too.
Finally, we convert the decimal part to add up to feet and the fraction part to the inches. By this method, you can easily overload operators for your own types.

Implicit and Explicit Cast

Implicit cast means automatic cast from one data type to another. Say you declare

C#
int i = 10;

Now if you do:

C#
double d = i;

It lets you do this. This is because of the fact that double is actually capable of holding any integer value. This is called implicit cast operation. The compiler also does implicit casts itself.

Say you define class A and class B, so that B inherits A. So you can say:

C#
B b1 = new B();
A a1 = b1;

This is also implicit cast operation, but here the cast is done automatically by the compiler, as compiler knows that any object of the derived class can be held by the base reference. So the first case is the example of framework defined implicit cast operation, while the second is the example of compiler defined implicit cast.

Explicit cast on the other hand requires the user to make sure that the cast is valid. Thus if you want to store a variable double to a variable int, there might be a case when the value produces OverflowException. So if the user wants to defer the automatic detection of the cast operation, he can use Explicit cast operator.

C#
double d = 10.0d;
int i = (int)d;

Here (int) makes the variable d call its explicit cast operation which might throw OverflowException when value cannot be held to an integer variable.

Similar to this, the base class object when needed to refer to a derived class object, also requires an explicit cast.

Implicit Cast Operator Overload

Now as you are already clear about the implicit cast operation, let's take the example a bit further to overload the implicit cast operators.

C#
public static implicit operator int(Finch point)
{
    return point.Feet;
}

public static implicit operator float(Finch point)
{
    float value = point.Feet;
    value += (point.inch * 0.83f);
    return value;
}

public static implicit operator double(Finch point)
{
    double value = point.Feet;
    value += (point.inch * 0.83d);
    return value;
}
public static implicit operator decimal(Finch point)
{
    decimal value = point.Feet;
    value += Convert.ToDecimal((point.inch * 0.83d));
    return value;
}
public static implicit operator Finch(double point)
{
    decimal d = Convert.ToDecimal(point);
    Finch f = (Finch)d;
    return f;
}

In the above few static methods, you have already seen that I have overloaded the cast operator using implicit keyword. This will ensure that we can implicitly assign an object of Finch to a int, double, decimal or float variable. The implicit cast operation will call these static overloads and convert the value to appropriate types. As you can see, the basic rule is that you should always keep the overload operator as static.

Explicit Overload

On the contrary, explicit overload requires an explicit call to the cast operators. The code looks almost similar with explicit keyword.

C#
public static explicit operator Finch(decimal point)
{
    Finch newinch = new Finch();
    checked
    {
        newinch.Feet = (int)decimal.Truncate(point);
        var value = point - newinch.feet;
        newinch.inch = (int)(.83f / Convert.ToSingle(value));
    }
    return newinch;
} 

This will ensure that a decimal point can be cast to Finch explicitly.

Now let us invoke these overloads:

C#
//implicit conversion of decimal to Finch
Finch f = 20.3;

//Invoke + operator overload
f = f + 2;
Console.WriteLine(f.ToString());

//cast to a double
double d = f;
Console.WriteLine("Double Part {0}", d);

//Cast to an integer
int i = f;
Console.WriteLine("Integer Part {0}", i);

Console.Read();

I hope you like my post. If you want any clarifications regarding this post, feel free to comment.

Thank you.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
President
India India
Did you like his post?

Oh, lets go a bit further to know him better.
Visit his Website : www.abhisheksur.com to know more about Abhishek.

Abhishek also authored a book on .NET 4.5 Features and recommends you to read it, you will learn a lot from it.
http://bit.ly/EXPERTCookBook

Basically he is from India, who loves to explore the .NET world. He loves to code and in his leisure you always find him talking about technical stuffs.

Working as a VP product of APPSeCONNECT, an integration platform of future, he does all sort of innovation around the product.

Have any problem? Write to him in his Forum.

You can also mail him directly to abhi2434@yahoo.com

Want a Coder like him for your project?
Drop him a mail to contact@abhisheksur.com

Visit His Blog

Dotnet Tricks and Tips



Dont forget to vote or share your comments about his Writing

Comments and Discussions

 
GeneralMy vote of 2 Pin
Liero_5-Apr-15 23:58
Liero_5-Apr-15 23:58 
Nothing new in the article comparing to oficial msdn documentation. Still not sure why you used checked blocks. the operator that takes dynamic is also not very good practice.
GeneralMy vote of 1 Pin
Sabarish R L6-Jul-14 11:46
Sabarish R L6-Jul-14 11:46 
General[My vote of 1] dynamic? WTF? I voted 1 Pin
Kubajzz11-Jul-10 2:20
Kubajzz11-Jul-10 2:20 
GeneralThanks for your valuable feedback. I really appreciate it. Pin
Abhishek Sur12-Jul-10 11:21
professionalAbhishek Sur12-Jul-10 11:21 
GeneralRe: Thanks for your valuable feedback. I really appreciate it. Pin
Kubajzz12-Jul-10 22:34
Kubajzz12-Jul-10 22:34 
GeneralRe: Thanks for your valuable feedback. I really appreciate it. Pin
Abhishek Sur13-Jul-10 12:25
professionalAbhishek Sur13-Jul-10 12:25 
GeneralRe: Thanks for your valuable feedback. I really appreciate it. Pin
Kubajzz14-Jul-10 10:38
Kubajzz14-Jul-10 10:38 
GeneralRe: Thanks for your valuable feedback. I really appreciate it. Pin
Abhishek Sur16-Jul-10 10:15
professionalAbhishek Sur16-Jul-10 10:15 
GeneralRe: Thanks for your valuable feedback. I really appreciate it. Pin
liquidthoughts14-Apr-14 0:00
liquidthoughts14-Apr-14 0:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.