Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Different approaches to Casting

, 16 Mar 2011
Rate this:
Please Sign up or sign in to vote.
Different approaches to Casting

Introduction

Conversion from one type to another is the most common programming need of our daily activities. We need cast operation almost for all applications we create. Few of them require regular type conversion while others require you to specify the cast on an expression. In BCL, there are few libraries available to you which might help you to do this casting for you. All these are very specific to a situation and the choice between them is the one most of you are confused about. In this post, I will try to cover all of these scenarios and let you rethink it before writing conversions.

Implicit Type Conversion

This is the most basic conversion in which the type of the data is modified without any prior truncation of existing data. The implicit type conversion is automatic and does not require any special treatment to the instruction set. The implicit type conversion occurs when a variable of small integral type is stored into a reference of larger integral type or a derived class object is stored in base class reference. As for example:

int i = 10;
long l = i;

Here the target time is larger in size than the source. Hence, there is no probability of producing a truncation or a leak in this case and the compiler allows this conversion.

At the same time, this rule is also valid for base – derived types where the derived class object can be cast easily to the base class as base class reference is lower in object hierarchy than derived class objects.

IEnumerable<object> lst = new List<object>();

Explicit Type Conversion

In case of explicit type conversion, the object is not converted automatically but it needs an explicit cast expression before the assignment. This cast is evaluated at runtime and compiler will generate an exception if the cast is not valid. The explicit cast can sometimes produce data truncate as either a large integral value is tried to store into a smaller type or base class object is tried to store in derived reference. For instance,

long l = 10;
int i = (int)l;

In the above case, we need to explicitly specify the type cast to the expression. Hence in this case, the explicit cast takes place.

If you look into IL, it will do a conv.I4 which means the 64 bit integer will be converted to 32 bit integer.

On the other hand, in case of reference types, you can even do the same using cast operation and it will call either explicit cast operator or will call the operator of base types. The explicit cast may generate InvalidCastException at runtime.

Userdefined Conversion

In case you need to define implicit or explicit cast for your own types, you might also have an option to overload cast operators. The cast operator can be overridden so that based on object relationship you might easily do the conversion yourself.

You can read more about user defined conversion from here.

Using the Library

.NET base class library provides you with a number of classes that help you to do these casts. System.Convert is one of the most important classes that let you change types.

Let me demonstrate this class a bit using my favourite tool Reflector.

Convert is actually a static class which enumerates all commonly known types into an array during its static construction. During each cast, the object is checked with the actual type and based on which the cast is properly taken. Let's look into Convert.ChangeType.

The definition for the method looks like:

Here you can see, the ChangeType actually breaks the entire cast into few parts.

  1. It checks whether the object we pass is null and the Type to which we are to convert is nullable, if so, it returns null.
  2. It tries to cast the value to IConvertible, a generic interface from which every CLR type (like int, char, byte, etc.) is inherited from. Thus if the value is any CLR Type, it should be cast as IConvertible. Otherwise InvalidCastException is thrown.
  3. Otherwise Type is checked and specific conversion is invoked. If the type is Object, it will return the value directly without any cast.
Thus ChangeType does nothing when you pass a User Defined Type while it does its own conversion when CLR Type is passed.

Now let me look at how the CLR type conversion is executed. To do this, let me look into the definition of System.Int32 (int):


So inside the type, the IConvertible is eventually calling the Convert classes. Now let me look into Convert.ToInt16, so we are going to cast an int32 into int16. The code would look like:

Hence, eventually every cast is internally a Conv call in IL. The BCL wrapper class Convert is actually the best implementation of implicit or explicit casts by properly throwing exceptions when data overflow occurs.

Note

I must also address that System.Convert is at its best to handle nullables. It does automatic box/unbox effectively when it comes to the point of changing from value type to reference. During this conversion, the Convert method automatically checks for null value and returns the default value for that particular type.

Casting an Anonymous Type

Anonymous type is new to .NET. It is introduced with .NET 3.5. The concept is very simple, anonymous types are created using new operator which ultimately creates a strongly typed class internally in IL after being compiled. You should remember, CLR is capable of finding appropriate type if the anonymous type appropriately matches another in the same assembly. Hence casting in anonymous type is possible if you know the structure of the object. Let's see the code below:

var x = new { X = 10, Y = 20 };
object boxedX = x;
//Now Unboxing
var unboxed = UnboxAnnonymousType(new { X = 0, Y = 0 }, boxedX);

// Now to get it unboxed

private static T UnboxAnnonymousType<T>(T example, object value)
{
    return (T)value;
}

In the above code, the compiler automatically finds the appropriate anonymous type for the variable x which is created anonymously using new operator in the first line with properties to hold X and Y. So passing the object of same type to UnboxAnnonymousType appropriately casts the same type from object. Thus invokes castclass operator and the conversion is valid.

Conclusion

Even though this is the most basic article, but still I had fun creating this. Hope you find it useful.

Thanks for reading. Post your feedback.

License

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

Share

About the Author

Abhishek Sur
Architect
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.
 
Presently he is working in WPF, a new foundation to UI development, but mostly he likes to work on architecture and business classes. ASP.NET is one of his strength as well.
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
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 5 PinmvpKunal_Chowdhury8-Feb-11 0:46 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 16 Mar 2011
Article Copyright 2011 by Abhishek Sur
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid