動的な型と動的バインディングに関連する警告を解決する

この記事では、次のコンパイラ エラーについて説明します。

  • CS1962: typeof演算子は、dynamic型では使用できません。
  • CS1964: 式に動的変換を適用できません。
  • CS1965: dynamic型から派生することはできません。
  • CS1966: 構築された動的型から派生することはできません。
  • CS1967: dynamic型を型制約として使用できません。
  • CS1968: 構築された動的型を型制約として使用できません。
  • CS1969: 動的式をコンパイルするために必要な 1 つ以上の型が見つかりません。
  • CS1970: 'System.Runtime.CompilerServices.DynamicAttribute' を使用しないでください。代わりに 'dynamic' キーワードを使用してください。
  • CS1971: メンバーへの呼び出しは動的にディスパッチする必要がありますが、これは基本アクセス式の一部であるためにできません。動的引数をキャストするか、ベース アクセスを削除することを検討してください。
  • CS1972: インデクサー アクセスは動的にディスパッチする必要がありますが、これは基本アクセス式の一部であるためにできません。動的引数をキャストするか、ベース アクセスを削除することを検討してください。
  • CS1973: 動的引数の型が拡張メソッドのターゲット パラメーター型と一致しません。
  • CS1974: 条件付きメソッドへの動的ディスパッチは実行時に失敗します。
  • CS1975: コンストラクター呼び出しは動的にディスパッチする必要がありますが、コンストラクター初期化子の一部であるためにできません。動的引数をキャストすることを検討してください。
  • CS1976: 動的にディスパッチされた操作の引数としてメソッド グループを使用できません。
  • CS1977: 動的にディスパッチされた操作の引数としてラムダ式を使用することはできません。
  • CS1978: 動的にディスパッチされた操作の引数として式を使用することはできません。
  • CS1979: 動的型のソースまたは結合シーケンスを持つクエリ式は使用できません。
  • CS1980: コンパイラで必要な型がないため、'dynamic' を使用するクラスまたはメンバーを定義できません。
  • CS1981: "is dynamic" パターンは誤解を招きます。代わりに 'is object' を使用してください。
  • CS7083: 式は暗黙的に 'System.Object' に変換できる必要があります。または、型 'dynamic' を使用できません。
  • CS8133: 動的オブジェクトを分解できません。
  • CS8364: 'nameof' の引数では、動的操作を使用できません。
  • CS8416: 非同期修飾子は、動的属性の式では使用できません。
  • CS9230: 型を持つ式に対して動的呼び出しを実行できません。

型宣言と制約で dynamic を使用する

  • CS1962: typeof 演算子は、 dynamic 型では使用できません。
  • CS1965: dynamic型から派生することはできません。
  • CS1966: 構築された動的型から派生することはできません。
  • CS1967: dynamic型を型制約として使用できません。
  • CS1968: 構築された動的型を型制約として使用できません。
  • CS1970: 'System.Runtime.CompilerServices.DynamicAttribute' を使用しないでください。代わりに 'dynamic' キーワードを使用してください。

dynamicは、実行時の操作に遅延バインディングを提供します。 型宣言、制約、継承、リフレクション操作など、コンパイラがコンパイル時に型情報を必要とするコンテキストで具象型を使用します。

  • リフレクション操作には具象型を使用します。 dynamic演算子でtypeofの代わりに特定の型を使用する (CS1962)
  • 継承には具象型を使用します。 dynamicの代わりに具象基底クラスを指定します (CS1965、CS1966)。
  • 具象型制約を使用します。 dynamicの代わりにジェネリック パラメーターに具象型制約を指定します (CS1967、CS1968)。
  • 変数には dynamic キーワードを使用します。 動的変数を宣言するには、常に dynamic キーワードを使用します。 DynamicAttributeを直接適用しないでください (CS1970):

dynamic型とその適切な使用方法の詳細については、「動的型の使用」を参照してください。

動的操作の制限

  • CS1964: 式に動的変換を適用できません。
  • CS1971: メンバーへの呼び出しは動的にディスパッチする必要がありますが、これは基本アクセス式の一部であるためにできません。動的引数をキャストするか、ベース アクセスを削除することを検討してください。
  • CS1972: インデクサー アクセスは動的にディスパッチする必要がありますが、これは基本アクセス式の一部であるためにできません。動的引数をキャストするか、ベース アクセスを削除することを検討してください。
  • CS1973: 動的引数の型が拡張メソッドのターゲット パラメーター型と一致しません。
  • CS1975: コンストラクター呼び出しは動的にディスパッチする必要がありますが、コンストラクター初期化子の一部であるためにできません。動的引数をキャストすることを検討してください。
  • CS1976: 動的にディスパッチされた操作の引数としてメソッド グループを使用できません。
  • CS1977: 動的にディスパッチされた操作の引数としてラムダ式を使用することはできません。
  • CS1978: 動的にディスパッチされた操作の引数として式を使用することはできません。
  • CS1979: 動的型のソースまたは結合シーケンスを持つクエリ式は使用できません。
  • CS8133: 動的オブジェクトを分解できません。
  • CS8364: 'nameof' の引数では、動的操作を使用できません。
  • CS8416: 非同期修飾子は、動的属性の式では使用できません。
  • CS9230: 型を持つ式に対して動的呼び出しを実行できません。

動的バインディングは実行時に柔軟性を提供しますが、特定の操作にコンパイル時の型情報が必要な場合は、動的値を特定の型にキャストします。

  • 基本メンバーを呼び出す前に動的引数をキャストする: 基本メンバー、インデクサー、またはコンストラクター (CS1971、CS1972、CS1975) を呼び出す前に、動的引数を特定の型にキャストします。

    class Base
    {
        public virtual void Method(object obj) { }
        public virtual int this[int index] => 0;
        public Base(int value) { }
    }
    
    class Derived : Base
    {
        public Derived(dynamic value) : base((int)value) { }  // Cast before calling base constructor
    
        public override void Method(object obj)
        {
            dynamic d = obj;
            base.Method((object)d);  // Cast before calling base method
        }
    
        public override int this[int index]
        {
            get
            {
                dynamic d = index;
                return base[(int)d];  // Cast before accessing base indexer
            }
        }
    }
    
  • デリゲートまたはラムダを渡す前に、特定の型にキャストします。 メソッド グループ、ラムダ式、またはデリゲート (CS1976、CS1977、CS1978) を渡す前に、動的オブジェクトを具象型にキャストします。

    dynamic d = GetDynamicObject();
    
    // Avoid:
    d.ProcessData(Console.WriteLine);  // CS1976
    d.ProcessData(x => x * 2);         // CS1977
    
    // Recommended:
    ((IProcessor)d).ProcessData(Console.WriteLine);  // Cast first
    ((IProcessor)d).ProcessData(x => x * 2);         // Cast first
    
  • LINQ クエリに具象型を使用する: LINQ クエリ ソースと結合シーケンスには、 dynamic の代わりに具象型を使用します (CS1979)。

    dynamic data = GetData();
    
    // Avoid:
    var query = from item in data  // CS1979
                select item;
    
    // Recommended:
    IEnumerable<MyType> typedData = data;
    var query = from item in typedData
                select item;
    
  • タプル要素に個別にアクセスする: 動的タプルで分解を使用する代わりに、タプル要素に個別にアクセスします (CS8133):

    dynamic tuple = (1, 2);
    
    // Avoid:
    var (a, b) = tuple;  // CS8133
    
    // Recommended:
    var a = tuple.Item1;
    var b = tuple.Item2;
    
  • 型情報を必要とする操作には、コンパイル時の式を使用 します。コンパイル時の型情報を必要とする操作には具象型を使用します (CS1964、CS1973、CS8364、CS8416、CS9230)。

    dynamic value = GetValue();
    
    // Avoid:
    var name = nameof(value.Property);  // CS8364
    
    // Recommended:
    MyType typedValue = value;
    var name = nameof(typedValue.Property);  // Use concrete type
    

動的バインディングとその制限の詳細については、「 動的型の使用」を参照してください。

動的なランタイム のサポートがありません

  • CS1969: 動的式をコンパイルするために必要な 1 つ以上の型が見つかりません。'Microsoft.CSharp.dll' への参照がありませんか?
  • CS1980: コンパイラで必要な型が見つからないため、'dynamic' を使用するクラスまたはメンバーを定義できません。参照がありませんか?
  • CS7083: 式は暗黙的に 'System.Object' に変換できる必要があります。または、型 'dynamic' を使用できません。

コンパイラは、動的操作 (CS1969、CS1980、CS7083) のコードを生成するために、 System.Runtime 名前空間と動的言語ランタイム (DLR) からの型を必要とします。 プロジェクトに必要な参照が含まれていることを確認します。 必要な型は、すべての最新の .NET (.NET 5 以降) プロジェクトに含まれています。 .NET Framework プロジェクトの場合は、プロジェクト ファイル内の Microsoft.CSharp.dll への参照を追加します。

動的な型の要件の詳細については、「動的 型の使用」を参照してください。

動的ディスパッチの警告

  • CS1974: 動的 にディスパッチされたメソッドの呼び出しは、1 つ以上の適用可能なオーバーロードが条件付きメソッドであるため、実行時に失敗する可能性があります。
  • CS1981: "is dynamic" パターンは誤解を招きます。部分式のランタイム型が 'dynamic' になることはありません。代わりに 'object' を使用することを検討してください。

[Conditional]属性を持つメソッドを呼び出す場合は、動的ディスパッチを使用しないでください。 コンパイラは、動的バインディングを使用して条件付きメソッド属性を検証できないため、ランタイム エラーが発生する可能性があります (CS1974)。 最初に動的式を実際の型にキャストします。

dynamic d = GetObject();

// Avoid:
d.ConditionalMethod(); // CS1974 - can fail at runtime

// Recommended:
MyClass obj = (MyClass)d;
obj.ConditionalMethod(); // Compile-time checks ensure correctness

値が null 以外かどうかを確認する場合は、is objectの代わりにis dynamicを使用します。 dynamic キーワードはコンパイル時のコンストラクトであり、オブジェクトのランタイム型がdynamicされることはありません (CS1981):

// Avoid:
if (someValue is dynamic) // CS1981 - always evaluates to false
{
    // This code never executes
}

// Recommended:
if (someValue is object) // Correctly checks if non-null
{
    // This code executes for non-null values
}

動的ディスパッチとランタイム動作の詳細については、「 動的型の使用」を参照してください。