V3068. Calling overrideable class member from constructor is dangerous.
Анализатор обнаружил потенциально возможную ошибку внутри конструктора класса - вызов перегружаемого (виртуального или абстрактного) метода.
Приведём пример, когда такая ситуация может привести к ошибке:
abstract class Base
{
protected Base()
{
Initialize();
}
protected virtual void Initialize()
{
...
}
}
class Derived : Base
{
Logger _logger;
public Derived(Logger logger)
{
_logger = logger;
}
protected override void Initialize()
{
_logger.Log("Initializing");
base.Initialize();
}
}
В нашем примере, в конструкторе абстрактного класса Base присутствует вызов виртуального метода Initialize. В классе Derived, унаследованном от класса Base, мы переопределяем метод Initialize, и используем в переопределённом методе поле _logger, которое инициализируется в конструкторе класса Derived.
Однако, при создании экземпляра класса Derived сначала будет выполнен конструктор самого базового класса в цепочке наследования (в нашем случае это Base). Но при вызове из конструктора Base метода Initialize, будет выполнен метод Initialize непосредственно у того объекта, который мы создаём в runtime - т.е. метод Initialize у класса Derived. Обратите внимание, что при выполнении метода Initialize поле _logger окажется ещё неинициализированным - создание экземпляра класса Derived из нашего примера приведёт к исключению NullReferenceException.
Таким образом, вызов переопределяемых методов в конструкторе потенциально может примести к выполнению методов объекта, инициализация которого ещё не завершена.
Для того, чтобы исправить предупреждение PVS-Studio, пометьте вызываемый метод (или класс, его содержащий), как sealed, либо снимите его пометку, как виртуального.
В случае, если вы точно уверены, что вам нужно описанное поведение при инициализации объекта и вы хотите скрыть предупреждение от анализатора, пометьте сообщение как ложнопозитивное. Информация о том, как это сделать, вы можете посмотреть в нашей документации.
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V3068. |