При создании B возникнет NullReferenceException: конструктор A вызывает B.Foo до выполнения тела конструктора B, где создаётся builder. Строка в консоль не выводится.
Какой вывод будет у виртуального метода, вызываемого из конструктора абстрактного класса
При создании B возникнет NullReferenceException: конструктор A вызывает B.Foo до выполнения тела конструктора B, где создаётся builder. Строка в консоль не выводится.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Какой результат выведет программа? Появится ли ошибка во время выполнения?
B obj = new B{};
abstract class A
{
protected A()
{
this.Foo();
}
protected abstract void Foo();
}
class B : A
{
private StringBuilder builder;
public B()
{
builder = new StringBuilder();
builder.Append("hello");
}
protected override void Foo()
{
builder.Append(" world ");
Console.WriteLine(builder);
}
}
Ответ
При создании B возникнет NullReferenceException: конструктор A вызывает B.Foo до выполнения тела конструктора B, где создаётся builder. Строка в консоль не выводится.
Виртуальная диспетчеризация действует и во время построения объекта. Поле builder пока равно null, поэтому исключение возникает на builder.Append, ещё до Console.WriteLine.
Предполагается наличие using System.Text. Главный способ исправления — не вызывать переопределяемые методы из конструктора базы; выполнение, зависящее от готового состояния, переносится после конструирования. Перенос инициализации поля может исправить этот пример, но не устраняет общий риск такого дизайна.