Правила C # очень отличаются от правил Java и C ++.
Когда вы находитесь в конструкторе для какого-либо объекта в C #, этот объект существует в полностью инициализированной (просто не «сконструированной») форме как его полностью производный тип.
namespace Demo
{
class A
{
public A()
{
System.Console.WriteLine("This is a {0},", this.GetType());
}
}
class B : A
{
}
// . . .
B b = new B(); // Output: "This is a Demo.B"
}
Это означает, что если вы вызываете виртуальную функцию из конструктора A, она преобразуется в любое переопределение в B, если оно предусмотрено.
Даже если вы намеренно настроите A и B таким образом, полностью понимая поведение системы, вы можете быть в шоке позже. Скажем, вы вызывали виртуальные функции в конструкторе B, «зная», что они будут обрабатываться B или A в зависимости от ситуации. Затем проходит время, и кто-то еще решает, что ему нужно определить C и переопределить некоторые виртуальные функции там. Внезапно конструктор B в конечном итоге вызывает код на C, что может привести к довольно неожиданному поведению.
Вероятно, в любом случае неплохо бы избегать виртуальных функций в конструкторах, поскольку правила настолько различны в C #, C ++ и Java. Ваши программисты могут не знать, чего ожидать!