次の方法で共有


ジェネリック型パラメーターとジェネリック型引数に関連するエラーと警告を解決する

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

  • CS0080: 非ジェネリック宣言では制約を使用できません。
  • CS0081: 型パラメーター宣言は、型ではなく識別子である必要があります。
  • CS0224: vararg を持つメソッドは、ジェネリックにすることも、ジェネリック型にすることも、params パラメーターを持つことはできません。
  • CS0304: new()制約がないため、変数型のインスタンスを作成できません。
  • CS0305: ジェネリック型を使用するには、N 個の型引数が必要です。
  • CS0306: 型を型引数として使用することはできません。
  • CS0307: 識別子はジェネリック メソッドではありません。式リストを使用する場合は、式の周りにかっこを使用します。
  • CS0308: 非ジェネリック型または非ジェネリック メソッドを型引数と共に使用することはできません。
  • CS0310: ジェネリック型またはメソッドでパラメーターとして使用するには、パブリック パラメーターなしのコンストラクターを持つ非抽象型である必要があります。
  • CS0311: ジェネリック型またはメソッドで型パラメーター T として型を使用することはできません。type1 から type2 への暗黙的な参照変換はありません。
  • CS0312: 型 'type1' は、ジェネリック型またはメソッドの型パラメーターとして使用できません。ヌル許容型 'type1' は制約を満たすことができません。
  • CS0313: 型 'type1' は、ジェネリック型またはメソッドの型パラメーターとして使用できません。null 許容型 'type1' が制約を満たしていません。Null 許容型は、どのインターフェイス制約も満たできません。
  • CS0314: ジェネリック型またはメソッドで型パラメーターとして型を使用することはできません。ボックス化変換または型パラメーター変換はありません。
  • CS0315: ジェネリック型またはメソッドで型パラメーター T として型を使用することはできません。ボックス化変換はありません。
  • CS0401: new()制約は、指定された最後の制約である必要があります。
  • CS0403: null 非許容値型である可能性があるため、null を型パラメーターに変換できません。代わりに default(T) を使用することを検討してください。
  • CS0405: 型パラメーターの制約が重複しています。
  • CS0412: パラメーター: パラメーター、ローカル変数、またはローカル関数は、メソッド型パラメーターと同じ名前を持つことはできません。
  • CS0413: クラス型制約もas制約もないため、型パラメーターを class 演算子と共に使用することはできません。
  • CS0417: 識別子: 変数型のインスタンスを作成するときに引数を指定できません。
  • CS0449: classstructunmanagednotnull、およびdefaultの制約を結合または複製することはできません。また、制約リストで最初に指定する必要があります。
  • CS0450: 型パラメーター: 制約クラスと class 制約または struct 制約の両方を指定できません。
  • CS0451: new()制約をstruct制約と共に使用することはできません。
  • CS0454: 型パラメーター 1 と型パラメーター 2 に関連する循環制約の依存関係。
  • CS0455: 型パラメーターは競合する制約を継承します。
  • CS0694: 型パラメーターの名前は、含まれている型またはメソッドと同じです。
  • CS0695: T は、一部の型パラメーターの置換に統合される可能性があるため、両方のインターフェイスを実装できません。
  • CS0698: ジェネリック型は属性クラスであるため、型から派生できません。
  • CS0702: 制約を特殊クラスにすることはできません。
  • CS0703: アクセシビリティに一貫性がありません:制約の型は宣言よりもアクセシビリティが低くなります。
  • CS0706: 制約の種類が無効です。制約として使用される型は、インターフェイス、非シール クラス、または型パラメーターである必要があります。
  • CS0717: 静的クラス: 静的クラスを制約として使用することはできません。
  • CS1961: 無効な分散: 型パラメーターは、型に対して有効にバリアントである必要があります。
  • CS7002: ジェネリック名の予期しない使用。
  • CS8322: 動的型の引数を、推論された型引数を持つジェネリック ローカル関数に渡すことはできません。
  • CS9011: キーワード delegate は制約として使用できません。 System.Delegateを意味しましたか?
  • CS9012: 予期しないキーワード recordrecord struct または record classを意味しましたか?
  • CS9338: 一貫性のないアクセシビリティ: 型はクラスよりもアクセスできません。

型パラメーターの宣言と名前付け

次のエラーは、ジェネリック型とメソッドで型パラメーターを宣言し、名前を付ける方法に関連しています。

  • CS0080: 非ジェネリック宣言では制約を使用できません。
  • CS0081: 型パラメーター宣言は、型ではなく識別子である必要があります。
  • CS0412: パラメーター: パラメーター、ローカル変数、またはローカル関数は、メソッド型パラメーターと同じ名前を持つことはできません。
  • CS0694: 型パラメーターの名前は、含まれている型またはメソッドと同じです。
  • CS9012: 予期しないキーワード recordrecord struct または record classを意味しましたか?

これらのエラーを修正するには、有効な識別子を使用して型パラメーターを宣言し、ジェネリック宣言にのみ制約句を適用し、スコープ内の他の識別子との名前付けの競合を回避します。

  • 非ジェネリック宣言 (CS0080) から制約句を削除します。 where句は、型パラメーターを宣言するジェネリック型とメソッドでのみ使用できます。制約では、型引数が満たす必要がある要件が定義されているためです。 制約を適用する必要がある場合は、最初に型またはメソッドの宣言に型パラメーターを追加します。 たとえば、public class MyClass where MyClass : System.IDisposablepublic class MyClass<T> where T : System.IDisposable に変更します。
  • 実際の型名を型パラメーター宣言の識別子に置き換えます (CS0081)。 具象型 (TTKeyなど) ではなく、識別子 (TValueintstringなど) を使用して型パラメーターを宣言する必要があります。 型パラメーターの目的は、ジェネリック型またはメソッドを使用するときに、コンパイラが実際の型に置き換えるプレースホルダーとして機能することです。 たとえば、public void F<int>()public void F<T>() に変更します。
  • 名前の競合を回避するために、型パラメーター、ローカル変数、またはパラメーターの名前を変更します (CS0412CS0694)。 型パラメーター名は、同じスコープ内の識別子をシャドウできません。 含まれている型またはメソッドの名前と一致することはできません。 このような競合により、どの識別子が参照されているかがあいまいになります。 たとえば、メソッド public void F<T>()がある場合は、そのメソッド内でローカル変数 double T 宣言することはできません。また、その包含型 (class C<C>) と同じ型パラメーターに名前を付けることはできません。
  • 正しいレコード宣言構文 (CS9012) を使用します。 レコード型を宣言するときは、 record class または record struct (または参照型の場合は record のみ) を使用する必要があります。 record キーワードだけでは、コンパイラが型宣言構文を想定している位置には表示できません。 たとえば、レコード型を宣言する場合は、別のキーワードが必要な場所にrecord class MyRecordを配置するのではなく、record struct MyRecordまたはrecordを記述します。

詳細については、「ジェネリック型パラメーターとジェネリックを参照してください。

制約の宣言と順序付け

次のエラーは、ジェネリック型パラメーターの制約の構文と順序に関連しています。

  • CS0401: new()制約は、指定された最後の制約である必要があります。
  • CS0449: classstructunmanagednotnull、およびdefaultの制約を結合または複製することはできず、制約リストで最初に指定する必要があります。
  • CS0450: 型パラメーター: 制約クラスと class 制約または struct 制約の両方を指定できません。
  • CS0451: new()制約をstruct制約と共に使用することはできません。
  • CS9011: キーワード delegate は制約として使用できません。 System.Delegateを意味しましたか?

型パラメーターの制約は、特定の順序に従う必要があります。プライマリ制約 (classstructunmanagednotnull、または default) の後にインターフェイスまたはクラスの制約が続き、最後に new() コンストラクター制約が続きます。 一部の制約は相互に排他的であり、組み合わせることはできません。

これらのエラーを修正するには:

  • new()制約を制約リストの末尾に配置します (CS0401)。 new()制約は、他のすべての制約の後に指定する必要があります。 たとえば、where T : new(), IDisposablewhere T : IDisposable, new() に変更します。
  • プライマリ制約を最初に配置し、相互に排他的な制約を組み合わせないでください (CS0449)。 classstructunmanagednotnull、またはdefaultのいずれかを指定でき、制約リストの先頭に表示する必要があります。 class制約とstruct制約は、classunmanagedと同様に相互に排他的です。 null 許容コンテキストでは、 class は既に notnullを意味するため、組み合わせることはできません。
  • 特定のクラス制約を struct (CS0450) と組み合わせないでください。 型パラメーターが特定のクラス型に制約されている場合は、暗黙的に参照型であり、 struct 制約と矛盾します。 クラス制約または struct 制約を削除します。
  • new()struct (CS0451) と組み合わせないでください。 すべての値型 (構造体) には暗黙的にパブリック パラメーターなしのコンストラクターがあるため、new()と組み合わせると、struct制約は冗長になります。 new()を使用する場合は、struct制約を削除します。
  • delegateを制約句のSystem.Delegateに置き換えます (CS9011)。 delegate キーワードは、制約としてではなく、デリゲート型を宣言するために使用されます。 型パラメーターをデリゲート型に制約するには、制約型として System.Delegate を使用します。 たとえば、where T : delegatewhere T : System.Delegate に変更します。

次の例は、正しい制約の順序を示しています。

using System;

// Primary constraint first, then interface constraints, then new()
class C<T> where T : class, IDisposable, new() { }

// struct doesn't need new() - it's implicit
class D<T> where T : struct, IComparable { }

// Delegate constraint using System.Delegate
class E<T> where T : System.Delegate { }

詳細については、「型パラメーターの制約」を参照してください。

型引数の数と使用法

次のエラーは、ジェネリック型とメソッドに正しい型引数の数と型を指定することに関連しています。

  • CS0224: vararg を持つメソッドは、ジェネリックにすることも、ジェネリック型にすることも、params パラメーターを持つことはできません。
  • CS0305: ジェネリック型を使用するには、N 個の型引数が必要です。
  • CS0306: 型を型引数として使用することはできません。
  • CS0307: 識別子はジェネリック メソッドではありません。式リストを使用する場合は、式の周りにかっこを使用します。
  • CS0308: 非ジェネリック型または非ジェネリック メソッドを型引数と共に使用することはできません。
  • CS7002: ジェネリック名の予期しない使用。

これらのエラーを修正するには、ジェネリック宣言で必要な型引数の正確な数を指定してください。 型引数として有効な型のみを使用します。 非ジェネリック コンストラクトには型引数を適用しないでください。

  • __arglist (CS0224) を使用するメソッドからジェネリック型パラメーターを削除するか、ジェネリック型宣言を含めます。 __arglist キーワードはジェネリックと互換性がありません。これは、可変引数リストを処理するためのランタイム メカニズムが、ジェネリック型パラメーターに必要な型置換と競合するためです。 この制限は、ジェネリック型内のジェネリック メソッドまたはメソッドと組み合わせて使用する場合、 params キーワードにも適用されます。
  • ジェネリック型またはメソッド宣言 (CS0305) で指定された型引数の正確な数を指定します。 ジェネリック型がインスタンス化されるときに、定義で宣言された各ジェネリック型パラメーターには、対応する型引数が必要です。 コンパイラは、型パラメーターごとに置き換える具象型を認識する必要があります。 たとえば、クラスがclass MyList<T>として宣言されている場合は、MyList<int>ではなく、MyList<int, string>など、クラスを使用するときに 1 つの型引数を指定する必要があります。
  • 型引数として有効な型のみを使用します (CS0306)。 ジェネリック型にはガベージ コレクターが追跡できるマネージド型が必要であり、ポインター型はアンマネージであるため、 int*char*などのポインター型は型引数として使用できません。 ジェネリック コンテキストでポインターを操作する必要がある場合は、ジェネリックと安全でないコードの混在を避けるために、 IntPtr の使用を検討するか、コードを再構築することを検討してください。
  • 非ジェネリック コンストラクト (CS0307、CS0308) から型引数構文を削除します。 山かっこで囲まれた型引数 ( <int> など) は、型パラメーターを宣言するジェネリック型とメソッドにのみ適用できます。 型引数を完全に削除するか、型のジェネリック バージョンを含む名前空間をインポートする必要があります。 たとえば、 IEnumerator<T> では using System.Collections.Generic; ディレクティブが必要ですが、 IEnumeratorSystem.Collections内にあります。
  • ジェネリック (CS7002) をサポートしていない宣言から型パラメーターを削除します。 列挙型などの一部のコンストラクトをジェネリックにすることはできません。 列挙型の値にジェネリック コンテナーが必要な場合は、代わりにジェネリック クラスまたは構造体を使用することを検討してください。

詳細については、「ジェネリック型パラメーターとジェネリックを参照してください。

コンストラクターの制約

次のエラーは、ジェネリック型パラメーターの new() 制約に関連しています。

  • CS0304: new()制約がないため、変数型のインスタンスを作成できません。
  • CS0310: ジェネリック型またはメソッドでパラメーターとして使用するには、パブリック パラメーターなしのコンストラクターを持つ非抽象型である必要があります。
  • CS0417: 識別子: 変数型のインスタンスを作成するときに引数を指定できません。

これらのエラーを修正するには、インスタンス化する必要がある型パラメーターに new() 制約を追加し、型引数にパブリック パラメーターなしのコンストラクターがあることを確認し、型パラメーターのインスタンスを構築するときに引数を渡さないようにします。

  • new()制約を型パラメーター宣言 (CS0304) に追加します。 new演算子を使用してジェネリック型またはメソッド内に型パラメーターのインスタンスを作成する場合、コンパイラは、実行時に指定された型引数にパラメーターなしのコンストラクターがあることを保証できる必要があります。 new()制約は、コンパイル時にこの保証を提供し、コンパイラが適切なインスタンス化コードを生成できるようにします。 たとえば、メンバー class C<T>T t = new T();がある場合は、宣言を class C<T> where T : new() に変更する必要があります。
  • 制約付き型パラメーターで使用される型引数 new() パブリック パラメーターなしのコンストラクター (CS0310) があることを確認します。 ジェネリック型またはメソッドが型パラメーターに対して new() 制約を宣言する場合、型引数として使用される具象型は非抽象型であり、パブリック パラメーターなしのコンストラクターを提供する必要があります。 型に非パブリック コンストラクター ( privateprotected コンストラクターなど) のみが含まれている場合、またはパラメーターを持つコンストラクターしかない場合、 new() 制約を満たすことはできません。 このエラーを修正するには、パブリック パラメーターなしのコンストラクターを型に追加するか、既に存在する別の型引数を使用します。
  • 型パラメーターをインスタンス化するときにコンストラクターの引数を削除します (CS0417)。 new()制約ではパラメーターなしのコンストラクターの存在のみが保証されるため、new T(arguments)に引数を渡すことはできません。これは、コンパイラが、これらの特定のパラメーター型を持つコンストラクターが、Tに置き換わる型に存在することを確認できないためです。 特定の引数を持つインスタンスを構築する必要がある場合は、ファクトリ メソッド、抽象ファクトリ パターン、または必要な構築動作を定義する特定の基底クラスまたはインターフェイス制約の使用を検討してください。

詳細については、「 型パラメーターの制約new() 制約」を参照してください。

制約充足と変換

次のエラーは、ジェネリック型パラメーターの制約を満たしていない型引数に関連しています。

  • CS0311: ジェネリック型またはメソッドで型パラメーター T として型を使用することはできません。暗黙的な参照変換はありません。
  • CS0312: ジェネリック型またはメソッドで型パラメーターとして型を使用することはできません。null 許容型が制約を満たしていません。
  • CS0313: ジェネリック型またはメソッドで型パラメーターとしてこの型を使用することはできません。null 許容型は制約を満たしていません。null 許容型は、いかなるインターフェイスの制約も満たすことができません。
  • CS0314: ジェネリック型またはメソッドの型パラメーターとして型を使用することはできません。ボックス化変換または型パラメーター変換はありません。
  • CS0315: ジェネリック型またはメソッド Tで型パラメーター TypeorMethod<T>として型を使用することはできません。ボックス化変換はありません。

これらのエラーを修正するには、適切な変換によってすべての制約を満たす型引数を使用し、派生クラスが基底クラスの制約を繰り返すようにし、null 許容値型に特別な制約要件があることを理解します。

  • 型引数を、制約型 (CS0311) への暗黙的な参照変換を持つ引数に変更します。 型パラメーターに where T : BaseType のような制約がある場合、暗黙的な参照変換または ID 変換によって、任意の型引数を BaseType に変換できる必要があります。 型引数は、それ自体 BaseType するか、 BaseTypeから派生するか、インターフェイスの場合は BaseType を実装する必要があります。 暗黙的な数値変換 ( short から int など) は、ジェネリック型パラメーターの制約を満たしていません。これらの変換は、参照変換ではなく値変換であるためです。
  • 派生クラス宣言 (CS0314) で基底クラスの型パラメーター制約を繰り返します。 派生ジェネリック クラスが、型パラメーターに制約がある基本ジェネリック クラスから継承する場合、派生クラスは対応する型パラメーターに対して同じ制約を宣言する必要があります。 派生クラスに指定された型引数が基底クラスの要件を満たすことをコンパイラが確認する必要があるため、これらの制約を繰り返す必要があります。 たとえば、 public class A<T> where T : SomeClassがある場合は、そこから派生するすべてのクラスを public class B<T> : A<T> where T : SomeClassとして宣言する必要があります。
  • null 非許容値型を使用するか、制約の型 (CS0312CS0313) を変更します。 null 許容値型 ( int? など) は、基になる値型とは異なり、同じ制約を満たしていません。 int?intの間に暗黙的な変換はありません。また、null 許容値型は、その基になる値型がインターフェイスを実装していても、null 許容ラッパー自体がインターフェイスを実装していないため、インターフェイスの制約を満たすことはできません。 これらのエラーを修正するには、値型の null 非許容形式を型引数として使用するか、必要に応じて、 object または null 許容参照型を受け入れるように制約を調整します。
  • 型引数が参照型またはクラス制約 (CS0315) を満たしていることを確認します。 型パラメーターがクラス型 ( where T : SomeClass など) に制約されている場合、制約リレーションシップを満たすボックス化変換がないため、型引数として値型 (構造体) を使用することはできません。 制約には、制約型との継承または実装リレーションシップを持つ参照型が必要です。 このエラーを解決するには、意味的に適切な場合は構造体をクラスに変更するか、ジェネリック型が値型で動作できる場合はクラス制約を削除します。

詳細については、「 型パラメーターの制約 」および 「暗黙的な変換」を参照してください。

ジェネリック型の利用制約

次のエラーは、ジェネリック型の使用方法に関する制限に関連しています。

  • CS0403: null 非許容値型である可能性があるため、null を型パラメーターに変換できません。代わりに default(T) を使用することを検討してください。
  • CS0413: クラス型制約もas制約もないため、型パラメーターを class 演算子と共に使用することはできません。
  • CS0695: 型は両方のインターフェイスを実装できません。また、一部の型パラメーターの置換で統一される可能性があるためです。
  • CS0698: ジェネリック型は属性クラスであるため、型から派生できません。
  • CS8322: 動的型の引数を、推論された型引数を持つジェネリック ローカル関数に渡すことはできません。
  • CS9338: 型のアクセシビリティがクラスよりも低くなっています。

これらのエラーを修正するには、制約のない型パラメーターのdefaultではなくnullを使用し、as演算子を使用するときにクラス制約を追加し、インターフェイスの統一の競合を回避し、ジェネリック属性クラスを作成せず、型引数が含まれるメンバーの可視性と一致することを確認します。

  • null割り当てをdefault(T)に置き換えるか、class制約を追加します (CS0403)。 制約のない型パラメーターに null を割り当てると、コンパイラは型引数が null 値を受け取る参照型であることを保証できません。これは、 intstructなどの値型であり、 nullできない可能性があるためです。 このエラーを解決するには、任意の型に適切な既定値 (参照型の場合は null、値型の場合は 0 または空) を提供する default(T) を使用するか、参照型のセマンティクスが特に必要で、classの割り当てを許可する場合は、型パラメーターにnull制約を追加します。
  • class演算子 (as) を使用する場合は、または特定の型制約を追加します。 as演算子は、変換が失敗した場合にnullを返す安全な型キャストを実行しますが、値型をnullできないため、この動作は値型と互換性がありません。 制約のない型パラメーターで as を使用すると、コンパイラは型引数が値型ではないことを保証できないため、コードが拒否されます。 このエラーを修正するには、 class 制約または特定の参照型制約 ( where T : SomeClass など) を追加して、型パラメーターが常に、失敗したキャストの null 結果を適切に処理できる参照型であることを確認します。
  • 統合可能な型パラメーターを使用して同じジェネリック インターフェイスを複数回実装しないでください (CS0695)。 クラスが異なる型パラメーター ( class G<T1, T2> : I<T1>, I<T2> など) を使用してジェネリック インターフェイスを複数回実装すると、両方のパラメーター (G<int, int>) に対して同じ型でインスタンス化されるリスクがあります。これにより、クラスが実質的に 2 回 I<int> 実装されるため、競合が発生します。 このエラーを解決するには、インターフェイスを 1 回だけ実装するか、型パラメーターを再構築して統一を防ぐか、異なる特殊化に個別の非ジェネリック クラスを使用します。
  • 属性クラス (CS0698) からジェネリック型パラメーターを削除します。

    このエラーは、現在のバージョンの C# では生成されません。ジェネリック属性がサポートされるようになりました。

  • 動的な値をジェネリック ローカル関数 (CS8322) に渡すときに、型引数を明示的に指定します。 ジェネリック ローカル関数に dynamic 引数を渡すと、実際の型はランタイムまで認識されないため、コンパイラは型引数を推論できません。 このエラーを修正するには、型引数 (たとえば、 LocalFunc<int>(d)) を明示的に指定するか、動的値を予期される型にキャストするか、非動的変数を使用します。
  • パブリックシグネチャまたはプロテクトシグネチャで使用される型引数が、少なくともそれらを使用するメンバーと同じくらいアクセス可能であることを確認します (CS9338)。 パブリックまたは保護されたジェネリック メンバーは、パブリックにアクセスできる型引数を使用する必要があります。 それ以外の場合、外部コードでメンバーの署名を正しく参照または使用できませんでした。 たとえば、public class Container<T>が内部型であるTがある場合、外部アセンブリはContainerを表示できますが、Tが表示されないため、適切に操作できません。 このエラーを修正するには、型引数をパブリックにするか、型引数のアクセシビリティに一致するようにメンバーを使用するメンバーのアクセシビリティを低下させます。

詳細については、「型パラメーター、既定値の式、および属性に関する制約」を参照してください。

有効な制約の種類

次のエラーは、ジェネリック型パラメーターの制約として無効な型を使用する場合に関連しています。

  • CS0405: 型パラメーターの制約が重複しています。
  • CS0702: 制約を特殊クラスにすることはできません。
  • CS0703: アクセシビリティに一貫性がありません:制約の型は宣言よりもアクセシビリティが低くなります。
  • CS0706: 制約の種類が無効です。制約として使用される型は、インターフェイス、非シール クラス、または型パラメーターである必要があります。
  • CS0717: static class: 静的クラスを制約として使用することはできません。

制約は、インターフェイス、非シール クラス、または型パラメーターである必要があります。 特定の型は、.NET 型システムでの特別な意味や継承できないため、制約として無効です。

これらのエラーを修正するには:

  • 重複する制約を削除します (CS0405)。 各制約は、制約句で 1 回だけ使用できます。 where T : I, Iがある場合は、重複を削除します。
  • 制約として特殊なクラスを使用しないでください (CS0702)。 ObjectArray、およびValueTypeの型は制約として使用できません。 すべての型は既に Objectから派生しているため、それに制約しても値は提供されません。 Array ValueTypeは、直接継承できない抽象基本型です。 配列のような動作が必要な場合は、代わりに IList<T> または IEnumerable<T> を使用します。
  • 制約の型がジェネリック型 (CS0703) と同程度にアクセスできることを確認します。 外部コードでは有効な型引数を指定できないため、パブリック ジェネリック型は内部型を使用して制約を持つことができません。 制約型をパブリックにするか、ジェネリック型のアクセシビリティを低下させます。
  • インターフェイス、非シール クラス、または型パラメーターのみを制約として使用します (CS0706)。 配列、シール クラス、構造体、列挙型、またはその他の無効な型を制約として使用することはできません。 特定の動作が必要な場合は、目的の型が実装するインターフェイスの使用を検討してください。
  • 静的クラスを制約として使用しないでください (CS0717)。 静的クラスには静的メンバーのみが含まれているため、拡張できません。 静的クラスから派生する型は存在しないため、制約として役に立ちません。 代わりに非静的クラスまたはインターフェイスを使用してください。

次の例は、有効な制約の種類を示しています。

public interface IMyInterface { }
public class MyBaseClass { }

// Valid: interface constraint
class A<T> where T : IMyInterface { }

// Valid: non-sealed class constraint
class B<T> where T : MyBaseClass { }

// Valid: type parameter constraint
class C<T, U> where T : U { }

詳細については、「型パラメーターの制約」を参照してください。

制約の競合と循環依存関係

次のエラーは、制約宣言での制約または循環依存関係間の競合に関連しています。

  • CS0454: 型パラメーター 1 と型パラメーター 2 に関連する循環制約の依存関係。
  • CS0455: 型パラメーターは競合する制約を継承します。

制約では循環依存関係を作成できません。型パラメーターは、同時に満たすことができない競合する制約を継承できません。

これらのエラーを修正するには:

  • 循環制約の依存関係を削除します (CS0454)。 型パラメーターは、制約によって直接または間接的にそれ自体に依存することはできません。 たとえば、where T : U where U : TTに依存し、UUに依存するため、Tは循環依存関係を作成します。 制約の 1 つを削除して、サイクルを中断します。
  • 競合する継承された制約を削除します (CS0455)。 C# では複数のクラス継承がサポートされていないため、型パラメーターを複数の関連のないクラスに制限することはできません。 同様に、これらの制約は相互に排他的であるため、 struct とクラス型の両方に制約することはできません。 型階層を再構築するか、競合する制約のいずれかを削除します。

次の例は、問題を示しています。

// CS0454: Circular dependency - T depends on U and U depends on T
class Circular<T, U> where T : U where U : T { }

// CS0455: Conflicting constraints - U can't derive from both B and B2
public class B { }
public class B2 { }
public class G<T> where T : B
{
    public class N<U> where U : B2, T { }
}

詳細については、「型パラメーターの制約」を参照してください。

型パラメーターの分散

次のエラーは、ジェネリック型パラメーターの分散修飾子に関連しています。

  • CS1961: 無効な共変性: 型パラメーターは型に対して正しく共変である必要があります。

分散修飾子 (反変性のin 、共変性の out ) は、インターフェイスとデリゲート宣言で型パラメーターを使用する方法を制御します。 共変 (out) 型パラメーターは出力位置 (戻り値の型) にのみ表示できますが、反変 (in) 型パラメーターは入力位置 (パラメーター型) でのみ使用できます。

このエラーを修正するには:

  • 戻り値の型にのみ表示される型パラメーターには、 out (共変) を使用します。 共分散によって、期待される派生度の低い型の代わりに、より派生度の高い型を使用することが可能になります。
  • パラメーター型にのみ表示される型パラメーターには、 in (反変) を使用します。 反変性により、派生度が高い型が必要な場合に、派生度が低い型を使用できます。
  • 入力位置と出力位置の両方に型パラメーターを指定する必要がある場合は、分散修飾子を削除します。

次の例は、正しい差異の使用法と正しくない差異の使用法を示しています。

// Incorrect: out T can't appear in input position
interface IWrong<out T>
{
    void Method(T arg);  // CS1961
}

// Correct: out T only in output positions
interface ICovariant<out T>
{
    T GetValue();
}

// Correct: in T only in input positions
interface IContravariant<in T>
{
    void Process(T arg);
}

// No modifier needed for both input and output
interface IInvariant<T>
{
    T Transform(T arg);
}

詳細については、「ジェネリックの 共変性と反変性」を参照してください。