Implicit and Explicit Object casting with Operator Overloading in C#

No.of Views2468
Bookmarked0 times
Downloads 
Votes0
By  abhi2434   On  10 Dec 2010 09:12:59
Tag : CSharp , General
Though this article I will discuss how to use cast operators implicit or explicit with arithmetic operation using operator overloading. Create common utility class as well.
emailbookmarkadd commentsprint

Images in this article missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at info@codegain.com

 

Introduction

Though this article I will discuss how to use cast operators implicit or explicit with arithmetic operation using operator overloading. Create common utility class as well.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.

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# Code

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

int i = 10;

Now if you do:

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:

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

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.

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.

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.

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:

//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();

Download Sample Project

Download source files -17 kb

Conclusion

In this article, i have given all details about casting and operator overloading.If you want any clarifications regarding this article, feel free to comment.thanl you for reading.

 
Sign Up to vote for this article
 
About Author
 
abhi2434
Occupation-Not Provided
Company-Not Provided
Member Type-Senior
Location-Not Provided
Joined date-22 Oct 2009
Home Page-Not Provided
Blog Page-Not Provided
 
 
Other popularSectionarticles
    Are you somewhat confused between Serialization and Marshaling? This writing would break this confusion up, it would give you a basic understanding of the process of Serialization and the process of Marshaling, and how you can get the most out of each.
    Published Date : 10/May/2010
    First, this writing concentrates of and compares between three programming languages, C#, C++/CLI, and ISO/ANSI C++. It discusses 9 rules that every developer should keep in mind while working with constructors, destructors, and finalizers and class hierarchies:
    Published Date : 05/May/2010
    This article explains how to filter rows in a DataSet/DataTable. The example provided will help you get information faster.
    Published Date : 23/May/2010
    In this article, I will explain three basic terms of C#, such as Call Stack ,Call Site and stack Unwinding
    Published Date : 17/Aug/2010
    In this article, I will discuss about Checked and unchecked keyword and conversions in C#.
    Published Date : 16/Aug/2010
Comments
There is no comments for this articles.
Leave a Reply
Title:
Display Name:
Email:
(not display in page for the security purphase)
Website:
Message:
Please refresh your screen using Ctrl+F5
If you can't read this number refresh your screen
Please input the anti-spam code that you can read in the image.
^ Scroll to Top
</