Animal a = new Dog();
You're creating two things, you're creating an object (Dog) and a reference variable (a). The object is a Dog, it will always be a Dog and part of being a Dog means also being an Animal. The variable you create is of type Animal and is pointing to the Animal part of the Dog object. As the object "a" points to is a Dog you could do this
Dog d = (Dog)a;
You still only have one object (Dog), however you have created another reference variable (d) that points to the Dog part of the object. So now you have one object (Dog) and two reference variables that point to this object; "a" which is looking at the Animal part and can only access Animal properties and methods, and "d" which is looking at the Dog part and can access any property or method on the Dog part or the Animal part (as Dog inherits Animal, Dog is considered an Animal too).
Now consider this
Cat c = (Cat)a;
Will this compile? Yes. The compiler only knows that "a" must be an animal, so it is *possible* that it might be a Cat but it doesn't know at compile time so it gives you the benefit of the doubt. However at run-time it will throw an error as there is no "Cat" part of the object that "a" points to, as "a" points to a Dog.