Поделиться через


CA2214: не вызывайте переопределяемые методы в конструкторах

TypeName

DoNotCallOverridableMethodsInConstructors

CheckId

CA2214

Категория

Microsoft.Usage

Критическое изменение

Не критическое

Причина

Конструктор незапечатанного типа вызывает виртуальный метод, определенный в его классе.

Описание правила

При вызове виртуального метода фактический тип, выполняющий метод, не выбирается до времени выполнения. Когда конструктор вызывает виртуальный метод, возможна ситуация, когда конструктор для экземпляра, вызывающего метод, не выполняется.

Устранение нарушений

Чтобы устранить нарушение этого правила, не вызывайте виртуальные методы типа из конструкторов типа.

Отключение предупреждений

Для этого правила отключать вывод предупреждений не следует. Нужно переделать конструктор, устранив вызов виртуального метода.

Пример

В следующем примере показаны последствия нарушения этого правила. Тестовое приложение создает экземпляр DerivedType, вызывающий выполнение конструктора базового класса (BadlyConstructedType). Конструктор BadlyConstructedType неверно вызывает виртуальный метод DoSomething. Судя по выходным данным, DerivedType.DoSomething() выполняется, причем до выполнения конструктора DerivedType.


Imports System

Namespace UsageLibrary

Public Class BadlyConstructedType
    Protected initialized As String = "No"


    Public Sub New()
        Console.WriteLine("Calling base ctor.")
        ' Violates rule: DoNotCallOverridableMethodsInConstructors.
        DoSomething()
    End Sub 'New

    ' This will be overridden in the derived type.
    Public Overridable Sub DoSomething()
        Console.WriteLine("Base DoSomething")
    End Sub 'DoSomething
End Class 'BadlyConstructedType


Public Class DerivedType
    Inherits BadlyConstructedType

    Public Sub New()
        Console.WriteLine("Calling derived ctor.")
        initialized = "Yes"
    End Sub 'New

    Public Overrides Sub DoSomething()
        Console.WriteLine("Derived DoSomething is called - initialized ? {0}", initialized)
    End Sub 'DoSomething
End Class 'DerivedType


Public Class TestBadlyConstructedType

    Public Shared Sub Main()
        Dim derivedInstance As New DerivedType()
    End Sub 'Main
End Class 
End Namespace
using System;

namespace UsageLibrary
{
    public class BadlyConstructedType
    {
        protected  string initialized = "No";

        public BadlyConstructedType()
        {
            Console.WriteLine("Calling base ctor.");
            // Violates rule: DoNotCallOverridableMethodsInConstructors.
            DoSomething();
        }
        // This will be overridden in the derived type.
        public virtual void DoSomething()
        {
            Console.WriteLine ("Base DoSomething");
        }
    }

    public class DerivedType : BadlyConstructedType
    {
        public DerivedType ()
        {
            Console.WriteLine("Calling derived ctor.");
            initialized = "Yes";
        }
        public override void DoSomething()
        {
            Console.WriteLine("Derived DoSomething is called - initialized ? {0}", initialized);
        }
    }

    public class TestBadlyConstructedType
    {
        public static void Main()
        {
            DerivedType derivedInstance = new DerivedType();
        }
    }
}

После выполнения примера получается следующий результат.