You can just type this:
Circle c = new Circle();
(Shape)c;
And it's valid C# - it just doesn't do anything useful because you discard the value you cast.
When you do this:
Circle c = new Circle();
Shape s = c;
You create two variables
c
and
s
, and you make them both refer to the same object. It's like cars: "this car" and "my car" can both reference the same vehicle in different ways.
When you create a class derived from a base class as you do with Circle and Shape, a Shape variable can hold a reference to any Shape object instance,
including all objects which are of a class derived from Shape because the action of deriving a class is saying "this new class is the base class, but it can do more as well".
And as a result, you can use the properties, methods, and events from the base class on any derived class instance. Going back to cars for a moment, If there is a base Car class, then you derive a manufacturer from that: Mercedes derives from Car, as do Ford, Ferrari, and Audi. That means that every vehicle Mercedes makes is a Car, but does not mean that every Ford is a Ferrari because they share a common base. A variable which contains a Car (such as "this car" or "that car", "my car" or "your car" can do anything that is common to all cars: CountTheWheels (always returns 4), GetTheColour (because all vehicles have a colour), Drive (because all vehicles drive in a very similar way). But you can't take a Mercedes variable and execute a Ford method on it: ServiceMyFord doesn;t exist for a my car, because Mr Ford didn't make it, Mr Benz did, and the service requirements are different.
The system uses the actual instance to work out what type it actually is and call the right method.
For example, Car may have a default DriveTo method, which Mercedes overrides, but which Ford overrides differently - When you call DriveTo on a Car variable the system looks at the contents, finds it's a Ford and calls the Ford version of the method automatically.
Does that make sense?