Possible Duplicate:
C# “as” cast vs classic cast
I want to know what happens under the hood of the .Net CLR when I do something like
object myObj = "abc"; string myStr = (string)myObj;
and how the second line differs from string myStr = myObj.ToString()
or string myStr = myObj as string;
looking around I found generics answers such as "the compiler inserts code there" but I'm not satisfied... I'm looking for deep undertanding of the cast mechanics... Oh the compiler inserts code? Show me! The compiler optmizes the code? How? When?
Pls get as close to the metal as you can!!!
You can use IL Dissasembler to see what is being produced by your code on a lower level. If you have Visual Studio installed on your machine, you should be able to find it just by typing "ildasm" in the windows search box.
Here's what the IL of the following code looks like:
A cast is primarily a compile time construct. It is your way of telling the compiler, "I know better than you, this instance that you think is such and such a type is * actually* of this other type. Just pretend that it's really this other type and let me use all of the methods/properties/fields/etc. of that other type.
At runtime very little changes. Pretty much the only thing that's added is a check to make sure that the instance really is of the type you were trying to cast to, and if it wasn't it will throw an exception. It's more or less:
As for
ToString
, it's merely a method that returns astring
. It's definition within thestring
class is most likely justreturn this;
. In any case, you're not technically casting anything, you're just calling a method that every object has that returns a string, and when that object is astring
under the hood you just happen to get that same object back. The key is that the compiler knows that the result of the method call is always a string, so nothing special needs to be done.You can use ILDASM, which comes with Visual Studio. It is an IL Disassembler.
Here is the code:
Here is what I got:
With ToString():
The IL is:
When you cast the string "abc" is stored in location 0 then location 0 is loaded the value is cast using "cast class [mscorlib]System.String" then that value is stored into location 1
When you call .ToString() it calls System.Object.ToString() on the string virtually. ToString() is defined in System.String
Here is the ILDASM for System.String.ToString():
It just returns itself.
CLR allows you to cast an object to its type or any of it's base type. A cast to base type is already considered safe and is implicit.
for eg.
Object s = new String();
But the CLR wants you to specify explicit cast when casting to a derived type
Now here what happens it s is not converted to string, but checked whether is of type String or not. If it is found to be of type String the cast is success else an InvalidCastExcetion is thrown.
Two more ways to case are using is and as operators
is Operator : This returns true if the cast succeeds else false.
e.g.
So before calling any method, normally you will write code like this
This is a little expensive because CLR casts twice.
To avoid this we have the as operator.
as Operator : Returns the reference to the type of object checked else returns null.
e.g. :
So you can see, there is a slight performance boost when using as operator.
That is all what the CLR has to offer when it comes to casting types.
When it comes to your code :
object str = "abc";
str.ToString() will call the ToString method of the System.object class which is a virtual method. When calling a virtual method, CLR will actually check the type of the object pointed by the caller.
Here str is actually pointing to a string object. So compiler will generate code to call the ToString method of the String class which will print the "abc" as output. This concept is polymorphism in which when calling a virtual method of any type, the actual object type is first obtained by the CLR and then appropiate method is called on the correct type of the object as String type in your case.