Think of it like this, you can cast Program to Test, because Program IS A Test.
You cannot cast Test to Program, because Test is not a Program.
It is ALWAY safe to downcast, to it only safe to upcast when you are sure the object IS of that type.
Needing to upcast is often a code smell, if you find you often need to upcast your objects, there's probably something wrong with your design.
Hope this helps,
EDIT: Is it always safe to downcast?
The act of downcasting is by definition - according to me - where you know the type of the object, and you're casting it lower down it's inheritance tree. e.g.
Cat and Dog both inherit from Animal, Oak and Birch both inherit from Tree.
it is ALWAYS safe to do this
public void DoThingWithCat(Cat snuggles)
{
snuggles.Meow();
DoThingWithAnimal(snuggles); // this is always OK, because we know
// the type of snuggles, and we know
// snuggles is an animal
}
This is an UpCast. It is not safe to do this, also this is a code is a code smell, there is probably something wrong with your object hierarchy if you need to do this.
public void DoSomethingElse(Animal anAnimal)
{
DoThingWithCat(anAnimal); // this is NOT always OK, because we
// DO NOT know the type of anAnimal,
// and it may not be a Cat
}
This is also unsafe, because it's straight casting, not necessarily up casting or down casting
public void DoSomethingDifferent(object anObject)
{
DoThingWithAnimal(anObject); // this may or may not work,
// depending on the type passed in,
// this is a recipe for disaster,
// because may not be an Animal,
// it could be a Tree.
}