I was wondering why some casts in C# are checked at compile-time whereas in other cases the responsibility is dumped on CLR. Like above both are incorrect but handled in a d
The compiler considers only the static types. The runtime checks the dynamic (runtime) type. Looking at your examples:
Other x = new Other();
Derived d = (Derived)x;
The static type of x is Other. This is unrelated to Derived so the cast fails at compile time.
Base x = new Base();
Derived d = (Derived)x;
The static type of x is now Base. Something of type Base might have dynamic type Derived, so this is a downcast. In general the compiler can't know from the static type of x if it the runtime type is Base, Derived, of some other subclass of Base. So the decision of whether the cast is allowed is left to the runtime.