I\'m a bit confused about what exactly object casting is and what it\'s used for. I\'ve read the MSDN documentation about Casting and type conversion, where I can see that f
You would cast to a specific object, whenever you want to use that specific type of object. Another way to cast to another type is
SomeType x = obj as SomeType;
Here you won't get an exception when obj is null. You should do a check for == null though.
You only need to use the cast operator when there is no implicit cast available that the compiler can verify is safe. If there is one and the compiler is sure the cast will succeed then it will do it for you automatically.
Now, why should I use a cast? You should use a cast when you either:
A
and you need an object of type B
and
there is a way to convert an A
into a B
.A
to an object and you need a
reference of type B
to that same object and both A
and B
are valid reference types to that object.Another way to think about it is:
And this brings up a way to group casts based upon what the cast is really doing:
The 1rst group are what we call reference conversions. These don't change the object at all, they simply change the type of the reference pointing to the object (evidently, they only apply to reference types, value types can not have reference conversions because you can't get a reference to a value type). Note that this type of cast is provided by the language itself, you can't implement reference conversions.
The second group are all the conversions that entail a representational change in the object, that is, the bits of the object returned by the cast are different to the the bits of the casted object. These type of casts are the implicit
and explicit
operators you can implement in any C# class/struct.
You can read more about this in this SO answer.
Ok all that is very interesting, but can you give me concrete examples? Yes, of course:
The compiler knows enough:
interface IFoo { }
class Foo: IFoo { }
IFoo foo = new Foo();
There is an implicit cast from Foo
to IFoo
in the last statement: IFoo foo = (IFoo)(new Foo());
. This cast will succeed always and the compiler knows there is an implicit cast (a reference conversion) from Foo
to IFoo
available, so it will do it for you.
I know better than the compiler:
object o = "Hello"; //'compiler knows enough' as all types are derived from object
var s = (string)o;
Here I know o
is really a string and I'm telling the compiler: even though you think o
is an object, trust me, I know its a string.
This is also a reference conversion. The string Hello
isn't touched in any way, the only thing we are changing is the reference pointing to it.
I know a given object of type A is convertible to another object of type B although no reference conversion exists.
short s = 1;
int i = s;
Note that a short
is not an int
but there happens to be a method (a cast operator) that knows how to convert a short
to an int
. Here we have an implicit cast from short
to int
. s
and i
have very different bits, but somebody implemented the necessary logic that turns a short into an int.
Now note that this is an implicit cast, you don't need to explicitly cast the short although nothing stops you from doing it. Its perfectly valid to do: int i = (int)s;
.
double d = 1.5;
int i = (int)d;
Here we have the same type of cast, but now its explicit. If you would have written int i = d
you'd get a compile time error because the cast is not implicit.
This brings up an interesting point that you seem to be conflating with casts; information loss. Its a good practice that implicit casts do not loose information while explicit cast are allowed to do so. This seems reasonable, you don't want the compiler to implicitly cast things losing information without telling you; when you cast a short
into an int
there is no risk, any short
fits into an int
. That is obviously not true when casting from double
to int
, hence the cast is implemented as explicit. (Note on implemented, this isn't enforced by the language, its a design decision of whoever wrote the class defining the cast operators).
A simple valid example goes back to older versions of C#. List<T>
didn't exist in that version and in order to store a collection of data you had to use a non-generic collection:
static void Main(string[] args)
{
ArrayList list = new ArrayList();
list.Add(1);
list.Add(2);
list.Add(3);
int total = 0;
foreach(object item in list)
total += (int)item; // without casting, compiler never knows item is int
Console.WriteLine("Total = {0}", total);
}
Another valid example is events, most events use the signature (object sender, EventArgs e)
. In order to access the elements of the sender, a button for example, then you need to cast:
Button btn = (Button)sender;
Console.WriteLine(btn.Text);
It is a better practice to use the as
operator over the normal casting to prevent null reference exception, but the above is just to provide valid examples.