An object reference can be:
An upcast always succeeds; a downcast succeeds only if the object is suitably typed.
Suppose we have the following class
class Shape{ public string Name; } class Circle : Shape // inherits from Shape { public long Radius; } class Square : Shape // inherits from Shape { public decimal Width; }
The following code is doing upcasting.
Circle myCircle = new Circle(); Shape a = myCircle; // Upcast
After the upcast, variable a still references the same Circle object as variable myCircle.
Console.WriteLine (a == myCircle); // True
Although a and myCircle refer to the identical object, a has a more restrictive view on that object:
Console.WriteLine (a.Name); // OK Console.WriteLine (a.Radius); // Error: Radius undefined
The last line generates a compile-time error because the variable a is of type Shape, even though it refers to an object of type Circle.
To get to its Radius field, you must downcast the Shape to a Circle.
The following code is doing a downcasting.
Circle myCircle = new Circle(); Shape a = myCircle; // Upcast Circle s = (Circle)a; // Downcast Console.WriteLine (s.Radius); // <No error> Console.WriteLine (s == a); // True Console.WriteLine (s == myCircle); // True
A downcast requires an explicit cast because it can potentially fail at runtime:
Square h = new Square(); Shape a = h; // Upcast always succeeds Circle s = (Circle)a; // Downcast fails: a is not a Circle
If a downcast fails, an InvalidCastException is thrown.