Я понимаю, что базовый класс не может быть преобразован в производный класс. Я не понимаю, почему это не поймано во время компиляции? Например:Ошибка передачи, не обнаруженная во время компиляции
class GradeBook
{
}
class ProfessorGradeBook : GradeBook
{
}
class Program
{
static void Main(string[] args)
{
ProfessorGradeBook a = (ProfessorGradeBook)new GradeBook();
//shouldn't this be a compile time error?
}
}
Я посмотрел на другие вопросы по StackOverflow, но она по-прежнему не имеет смысла для меня, почему это будет компилировать? ProfessorGradeBook a = (ProfessorGradeBook)new GradeBook();
никогда не удастся ни при каких обстоятельствах (правильно?), Так почему же это ошибка во время выполнения вместо ошибки времени компиляции?
EDIT:
Я уже знал, почему компилятор никогда бы не поймать этот:
GradeBook a = new ProfessorGradeBook();
ProfessorGradeBook b = (ProfessorGradeBook)a;
Во время выполнения, a
может указывать на что-либо, так что компилятор должен просто доверять вам. Я был больше озабочен, почему компилятор никогда бы не поймать этот:
ProfessorGradeBook a = (ProfessorGradeBook)new GradeBook();
Я предполагаю, что ответ, который имеет наибольший смысл в первый комментарий Эрик Липперта, в частности, «подавляющее большинство разработчиков никогда бы не ввести эту строку кода» поэтому команда компилятора никогда не была заинтересована в попытке сделать ошибку.
Это не проблема компиляции, так как компилятор отделить 2 команды. Сначала он создает новый экземпляр GradeBook, затем он пытается отличить объект от базового объекта, и это тоже хорошо. Компилятор не «знает», что этот объект является просто базовым объектом. –
Вкратце: команда компилятора могла потратить время и энергию на создание предупреждения или ошибки. Цель потратить эти ограниченные усилия состоит в том, чтобы ** решить реальные проблемы, которые реально существуют у реальных разработчиков **. Явная не-цель: ** найти во время компиляции любую возможную ошибку **. Компилятор может легко предупредить об этом. Это происходит не потому, что подавляющее большинство разработчиков просто никогда не набирают это в первую очередь. Предупреждение, которое никогда не срабатывает, потому что никто не набирает этот код впустую, что может быть потрачено на разработку более полезных предупреждений. –
Более конкретно, оператор литья имеет здесь очень специфическое значение; это означает, что «компилятор внимания», я пишу код, который вы не можете доказать, здесь является типичным. Я знаю, что он является типичным, доверяйте мне и разрешайте компиляции этого кода. Если я ошибаюсь, пожалуйста, провалите мою программу * «То есть, cast * явно отключает систему безопасности *. Компилятор вряд ли может быть обвинен в том, что не дал ошибку при выключении системы обнаружения ошибок! Когда вы пишете актерский состав *, вы несете ответственность за то, чтобы приведение было успешным, а не компилятор! –