Ответ 1
Это потому, что ключевое слово base отключает вызов виртуального метода, но кастинг не работает.
Позвольте сломать его:
С virtual
и override
s, С# имеет алгоритм для поиска правильного метода для вызова. Этот алгоритм называется вызовом виртуального метода.
Когда компилятор С# должен вызывать метод с модификатором override
, он пытается найти самый перегруженный метод. То есть, он опускается по иерархии наследования типа времени выполнения, чтобы найти наиболее сложный метод. В этом случае, когда вы кладете Student
в его базовый класс Person
, в время выполнения, то, что у вас действительно есть, является производным классом от Person
. Таким образом, компилятор С# пытается найти самый переопределенный метод, то есть метод, который существует в классе Student
, и вызывает этот метод. Но этот метод снова пытается передать Student
в Person
, и снова цепочка продолжается и продолжается. Таким образом, вы видите StackOverflowException
.
Однако, когда вы используете base
для вызова переопределенного базового метода, компилятор рассматривает этот метод (Person.UpdateLastLogin
) как не виртуальный метод и не будет применять вызов виртуального метода и разрешение на него.
Спецификация С# имеет довольно разумное объяснение в override
и virtual
. Я рекомендую вам прочитать разделы 17.5.3 Виртуальные методы и 17.5.4 Переопределить методы. Конкретно цитируется из спецификации:
Базовый доступ отключает механизм виртуального вызова и просто обрабатывает базовый метод как не виртуальный метод.