Есть несколько причин, по которым это преобразование разрешено.
Во-первых, как говорили люди в других ответах, оператор приведения означает, что я знаю больше, чем вы; Я гарантирую вам, что это преобразование пройдет успешно, и если я ошибаюсь, выкину исключение и завершу процесс. Если вы лжёте компилятору, произойдут плохие вещи; на самом деле вы не даете эту гарантию, и в результате программа выходит из строя.
Теперь, если компилятор может сказать, что вы ему лжете, он может уличить вас во лжи. Компилятору не требуется быть сколь угодно умным, чтобы поймать вас на вашей лжи! Анализ потока, необходимый для определения того, что выражение типа Base никогда не будет иметь тип Derived, сложен; значительно сложнее, чем логика, которую мы уже реализуем для обнаружения таких вещей, как неназначенные локальные переменные. У нас есть лучшие способы потратить наше время и усилия, чем улучшать способность компилятора уличать вас в очевидной лжи.
Поэтому компилятор обычно анализирует только типы выражений, а не возможные значения. Только из анализа типов невозможно узнать, будет ли преобразование успешным. Это может завершиться успешно, поэтому это разрешено. Запрещены только те приведения, о которых компилятор знает, что они всегда будут неудачными в результате анализа типов.
Во-вторых, можно указать (Derived)(new Base()), где Derived – это тип, который реализует тип Base и который не дает сбой во время выполнения. Также возможен сбой (Base)(new Base()) с недопустимым исключением приведения во время выполнения! Реальные факты! Это чрезвычайно редкие ситуации, но они возможны.
Подробнее читайте в моих статьях на эту тему:
person
Eric Lippert
schedule
17.11.2011
pне был изменен до приведения? - person John Saunders   schedule 17.11.2011