>
>
>
V3068. Calling overrideable class membe…


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.