In the last post I was puzzled by what I thought were some inconsistencies between using the cast operator and Convert.ToInt32 when trying to convert an object typed as a decimal to an int.
I had it tracked down at the ‘System.Convert’ class in the ‘mscorlib’ assembly we’ll find the following in the method definition for ‘ToInt32(object)’ using Reflector:
All that’s going on here is we’re using the underlying type’s implementation of the ‘IConvertible’ interface to perform the conversion. The System.Decimal class implements the ‘ToInt32’ method of ‘IConvertible’ like this:
There we finally see the heavy lifting that goes in to converting a decimal to an int. So why does the use of ‘Convert.ToInt32’ result in this method ultimately being called but performing the direct cast on an object doesn’t?
Let’s use that same code example from the previous post and crack it open with Reflector. In addition to displaying an approximation of what the original C# or VB .NET code might have looked like for a given assembly, Reflector also lets you peak at the intermediate language (MSIL). Looking at this intermediate language can sometimes give you a better feel for what’s really going on under the covers with a bit of code.
If we look at the IL for the code that failed with the InvalidCastException at runtime we can see what’s actually happening:
We can see the initial creation of the decimal variable (L_0008), boxing that value into an object (L_000f), and then the eventual attempt to unbox that value into an Int32 (L_0016). As I discovered previously, the C# spec explicitly disallows unboxing a type into something other than the the type that was initially boxed.
Let’s compare this with the code that (successfully) attempted to cast a decimal variable to an integer:
We can see the initial creation of the decimal variable (L_0013) and then a call to the ‘op_Explicit’ method of the System.Decimal type. This appears to be the difference between these two code snippets, so what is the ‘op_Explicit’ method?
This method defines an explicit cast operation that can be performed between the Decimal and Int32 types. This method gets treated just like the other defined operators (i.e. addition, subtraction, division, etc.). Just like the compiler gives us a nice readable syntax for dealing with these operators (i.e. using the ‘+’, ‘-‘, and ‘/’ characters to represent the operation), we also get a nice ‘( )’ operator as readable facade on top of the ‘op_Explicit’ method. If we use Reflector to take a look at the op_Explicit declaration we find the following:
All this is doing is calling out to the ‘ToInt32’ method that’s doing the real “heavy lifting” of performing this conversion.
So, after all of that I feel satisfied in understanding a bit more about the .NET framework, boxing, unboxing, and type conversion. Perhaps not immediately useful in my day to day life, but I’m a firm believer in understanding as much as I can about the tools that I use to do my job, whether it be the hardware, operating system, IDE, or development platform.