CA2214:コンストラクターのオーバーライド可能なメソッドを呼び出しません

プロパティ
ルール ID CA2214
Title コンストラクターのオーバーライド可能なメソッドを呼び出しません
[カテゴリ] 使用方法
修正が中断ありか中断なしか なし
.NET 8 では既定で有効 いいえ

原因

アンシールド型のコンストラクターからは、そのクラスに定義されている仮想メソッドが呼び出されます。

規則の説明

仮想メソッドが呼び出されると、そのメソッドを実行する実際の型は実行時まで選択されません。 コンストラクターから仮想メソッドを呼び出すと、メソッドを呼び出すインスタンスのコンストラクターが実行されないことがあります。 その場合、オーバーライドされた仮想メソッドが初期化とコンストラクターのその他の構成に依存している場合、エラーや予期しない動作が発生することがあります。

違反の修正方法

この規則の違反を修正するには、型のコンストラクター内から型の仮想メソッドを呼び出さないでください。

どのようなときに警告を抑制するか

この規則による警告は抑制しないでください。 仮想メソッドを呼び出さないよう、コンストラクターを再設計してください。

次の例からは、この規則に違反した場合の影響を確認できます。 テスト アプリケーションによって DerivedType のインスタンスが作成されます。これにより、その基底クラス (BadlyConstructedType) コンストラクターが実行されます。 BadlyConstructedType のコンストラクターによって、仮想メソッド DoSomething が間違って呼び出されます。 出力からわかるように、DerivedType のコンストラクターが実行される前に DerivedType.DoSomething() が実行されます。

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 Main2214()
    {
        DerivedType derivedInstance = new DerivedType();
    }
}

Imports System

Namespace ca2214

    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 Main2214()
            Dim derivedInstance As New DerivedType()
        End Sub 'Main
    End Class
End Namespace

この例を実行すると、次の出力が生成されます。

Calling base ctor.
Derived DoSomething is called - initialized ? No
Calling derived ctor.