foreach ステートメントと非同期列挙子のエラーと警告を解決する

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

  • CS0202: foreach では、'type.GetEnumerator()' の戻り値の型 'type' に、適切な public 'MoveNext' メソッドと public 'Current' プロパティが必要です
  • CS0230: foreach ステートメントでは型と識別子の両方が必要です
  • CS0278: 'type' は 'パターン名' パターンを実装していません。'method name' は 'method name' であいまいです。
  • CS0279: 'type' は 'パターン名' パターンを実装していません。'method name' はパブリック インスタンスまたは拡張メソッドではありません。
  • CS0280: 'type' は 'pattern name' パターンを実装していません。'method name' のシグネチャが正しくありません。
  • CS0446: Foreach は 'メソッド グループ' で操作できません。'メソッド グループ' を呼び出す予定でしたか?
  • CS1579: 'type' には 'member' のパブリック インスタンスまたは拡張定義が含まれていないため、foreach ステートメントは型 'type' の変数を操作できません
  • CS1640: 'interface' の複数のインスタンス化が実装されているため、foreach ステートメントは型 'type' の変数を操作できません。特定のインターフェイスインスタンス化にキャストしてみてください
  • CS8186: foreach ループは、その反復変数を宣言する必要があります。
  • CS8412: 非同期 foreach では、'method' の戻り値の型 'type' に適切なパブリック 'MoveNextAsync' メソッドとパブリック 'Current' プロパティが必要です
  • CS8413: 'interface' の複数のインスタンス化が実装されているため、型 'type' の変数に対して非同期 foreach ステートメントを操作できません。特定のインターフェイスインスタンス化にキャストしてみてください
  • CS8414: 'type' には 'member' のパブリック インスタンスまたは拡張定義が含まれていないため、foreach ステートメントは型 'type' の変数を操作できません。'foreach' ではなく 'await foreach' を意味しましたか?
  • CS8415: 'type' には 'member' のパブリック インスタンスまたは拡張定義が含まれていないため、型 'type' の変数に対して非同期 foreach ステートメントを操作できません。'await foreach' ではなく 'foreach' を意味しましたか?
  • CS8419: 非同期反復子メソッドの本体には、'yield' ステートメントを含める必要があります。
  • CS8420: 非同期反復子メソッドの本体には、'yield' ステートメントを含める必要があります。メソッド宣言から 'async' を削除するか、'yield' ステートメントを追加することを検討してください。
  • CS8424: パラメーター 'name' に適用された EnumeratorCancellationAttribute は無効です。この属性は、IAsyncEnumerable を返す非同期反復子メソッドの CancellationToken 型のパラメーターでのみ有効です。
  • CS8425: 非同期イテレーター 'method' には型 'CancellationToken' のパラメーターが 1 つ以上ありますが、そのいずれにも 'EnumeratorCancellation' 属性が適用されていないため、生成された 'IAsyncEnumerable<>.GetAsyncEnumerator' のキャンセル トークン パラメーターは消費されません
  • CS8426: 属性 [EnumeratorCancellation] を複数のパラメーターで使用できません
  • CS9353: 'type' には 'member' の定義が含まれていません。型 'type' の最初の引数を受け入れるアクセス可能な拡張メソッド 'member' が見つかりませんでした (代わりに 'await foreach' を使用して非同期コレクションを反復処理しますか?

foreach ステートメント構文

  • CS0230: foreach ステートメントでは型と識別子の両方が必要です
  • CS0446: Foreach は 'メソッド グループ' で操作できません。'メソッド グループ' を呼び出す予定でしたか?
  • CS8186: foreach ループは、その反復変数を宣言する必要があります。

これらのエラーは、コレクションの種類が有効かどうかに関係なく、 foreach ステートメント 自体の形式が正しくないことを示します。

型 (または var) と反復変数 (CS0230、 CS8186) の識別子の両方を宣言します。 foreach ステートメントには、ループ変数宣言が必要です。 型または名前は省略できません。 たとえば、foreach (int x in collection)ではなくforeach (int in collection)を記述します。

コレクション式として渡すのではなく、メソッドまたはデリゲートを呼び出します (CS0446)。 in句でかっこなしでメソッド グループまたはデリゲートを参照する場合、コンパイラはコレクション値を想定しているため、このエラーを報告します。 そのメソッドが列挙可能型 (foreach (var item in GetItems())) を返す場合は、メソッドを呼び出すためのかっこを追加します。

列挙可能なパターンの要件

  • CS0202: foreach では、'type.GetEnumerator()' の戻り値の型 'type' に、適切なパブリック 'MoveNext' メソッドとパブリック 'Current' プロパティが必要です
  • CS0278: 'type' は 'パターン名' パターンを実装していません。'method name' は 'method name' であいまいです。
  • CS0279: 'type' は 'パターン名' パターンを実装していません。'method name' はパブリック インスタンスまたは拡張メソッドではありません。
  • CS0280: 'type' は 'pattern name' パターンを実装していません。'method name' のシグネチャが正しくありません。
  • CS1579: 'type' には 'member' のパブリック インスタンスまたは拡張定義が含まれていないため、foreach ステートメントは型 'type' の変数を操作できません
  • CS8412: 非同期 foreach では、'method' の戻り値の型 'type' に適切なパブリック 'MoveNextAsync' メソッドとパブリック 'Current' プロパティが必要です

foreach ステートメントでは、特定のインターフェイスを必要とするのではなく、パターンベースのアプローチを使用します。 型を列挙可能にするには、次の値を指定する必要があります。

  • 戻り値の型がクラス、構造体、またはインターフェイスであるパブリック パラメーターなしのGetEnumerator メソッド (またはGetAsyncEnumeratorの場合はawait foreach)。
  • 列挙子の戻り値の場合: パブリック Current プロパティと、パラメーターなしのパブリック MoveNext メソッドで bool を返すもの (またはパラメーターなしのパブリック MoveNextAsync メソッドで Task<bool> を返すもの、ValueTask<bool>、または他の待機可能型であってその awaiter の GetResult メソッドにより bool 値を返すもの)。 列挙可能なパターンの詳細については、「 Iteration ステートメント - foreach」を参照してください。

配列またはポインター (GetEnumerator) ではなく、が適切な列挙子型を返していることを確認します。 戻り値は、それ自体が MoveNext および Currentを公開する型である必要があります。

型にパブリック GetEnumerator メソッドがない場合は追加します (CS1579)。 または、 IEnumerable<T> を実装するか、 GetEnumeratorという名前の拡張メソッドを指定します。 await foreachの場合は、GetAsyncEnumeratorを指定するか、IAsyncEnumerable<T>を実装します。

GetAsyncEnumerator から返す型はパブリック Current プロパティであってパラメーターなしのパブリック MoveNextAsync メソッドで Task<bool>, ValueTask<bool> を返すもの、または他の待機可能型であってその awaiter の GetResult メソッドにより bool 値 (CS8412) を返すものであることを確実にします。 これは CS0202 と同等の非同期です。

複数のメソッドがパターン名 (CS0278) と一致する場合のあいまいさを解決します。 この警告は、コンパイラが MoveNext または GetEnumeratorの 2 つの候補を見つけた場合に発生します。 競合するメンバーを削除または名前変更するか、特定のインターフェイスにキャストしてあいまいさを解消します。

パターン メソッドをパブリックメソッドと非静的メソッドにする (CS0279)。 列挙可能なパターンでは、 GetEnumerator、 MoveNext、 Current パブリック インスタンス メンバー (またはパブリック拡張メソッド) である必要があります。 internalまたはstaticメンバーをpublicインスタンス メンバーに変更します。

パターン メソッド (CS0280) のシグネチャを修正します。 たとえば、 MoveNext はパラメーターを受け取らず、 boolを返す必要があります。 フィールドまたはプロパティがメソッド名をシャドウする場合は、コンパイラが正しいメソッドを見つけられるように名前を変更します。

複数の列挙可能な実装

  • CS1640: 'interface' の複数のインスタンス化が実装されているため、foreach ステートメントは型 'type' の変数を操作できません。特定のインターフェイスインスタンス化にキャストしてみてください
  • CS8413: 'interface' の複数のインスタンス化が実装されているため、型 'type' の変数に対して非同期 foreach ステートメントを操作できません。特定のインターフェイスインスタンス化にキャストしてみてください

これらのエラーは、コレクション型が IEnumerable<T> (CS1640) または IAsyncEnumerable<T> (CS8413) の複数のジェネリック インスタンス化を実装し、列挙する要素の型に関するあいまいさを作成するときに発生します。

反復処理する前に、コレクションを特定のインターフェイスインスタンス化にキャストします。 たとえば、型が IEnumerable<int> と IEnumerable<string>の両方を実装する場合は、目的の要素型を選択する foreach (int i in (IEnumerable<int>)collection) を記述します。

不一致の foreach と await foreach

  • CS8414: 'type' には 'member' のパブリック インスタンスまたは拡張定義が含まれていないため、foreach ステートメントは型 'type' の変数を操作できません。'foreach' ではなく 'await foreach' を意味しましたか?
  • CS8415: 'type' には 'member' のパブリック インスタンスまたは拡張定義が含まれていないため、型 'type' の変数に対して非同期 foreach ステートメントを操作できません。'await foreach' ではなく 'foreach' を意味しましたか?
  • CS9353: 'type' には 'member' の定義が含まれていません。型 'type' の最初の引数を受け入れるアクセス可能な拡張メソッド 'member' が見つかりませんでした (代わりに 'await foreach' を使用して非同期コレクションを反復処理しますか?

これらのエラーは、foreach ステートメントの種類と、コレクション型が実装するインターフェイスとの間に不一致があることを示しています。

コレクションがawait foreachのみを実装する場合は、foreachではなくIAsyncEnumerable<T>を使用します (CS8414、CS9353)。 非同期列挙可能な型は、GetAsyncEnumeratorではなくGetEnumeratorを提供するため、await foreach メソッドでasyncを使用して反復処理する必要があります。

コレクションがforeachのみを実装する場合は、await foreachではなくIEnumerable<T>を使用します (CS8415)。 同期コレクションは GetAsyncEnumeratorを提供しないため、 await foreach は列挙できません。

非同期イテレーターメソッド本体

  • CS8419: 非同期反復子メソッドの本体には、'yield' ステートメントを含める必要があります。
  • CS8420: 非同期反復子メソッドの本体には、'yield' ステートメントを含める必要があります。メソッド宣言から 'async' を削除するか、'yield' ステートメントを追加することを検討してください。

これらのエラーは、メソッドのシグネチャが非同期反復子として宣言し ( async 、 IAsyncEnumerable<T> または IAsyncEnumerator<T>を返します)、本文に yield return または yield break ステートメントが含てられていない場合に発生します。

メソッド本体に少なくとも 1 つの yield return ステートメントを追加して、有効な非同期反復子メソッドにします。 メソッドを反復子にするつもりがない場合は、 async 修飾子を削除して戻り値の型を変更するか、代わりに別のソースから構築された非同期列挙型を返します。

反復子メソッドの詳細については、「 反復子 と yield ステートメント」を参照してください。

EnumeratorCancellation 属性の使用法

  • CS8424: パラメーター 'name' に適用された EnumeratorCancellationAttribute は無効です。この属性は、IAsyncEnumerable を返す非同期反復子メソッドの CancellationToken 型のパラメーターでのみ有効です。
  • CS8425: 非同期イテレーター 'method' には 'CancellationToken' 型のパラメーターが 1 つ以上ありますが、そのいずれも 'EnumeratorCancellation' 属性で修飾されていないため、生成された 'IAsyncEnumerable<>.GetAsyncEnumerator' から渡されるキャンセル トークン パラメーターは消費されません
  • CS8426: 属性 [EnumeratorCancellation] を複数のパラメーターで使用できません

これらの診断は、EnumeratorCancellationAttributeによって提供されるトークンにCancellationToken パラメーターを接続するGetAsyncEnumerator(CancellationToken)に関連します。

[EnumeratorCancellation] (CancellationToken) を返す非同期反復子メソッドでIAsyncEnumerable<T>型のパラメーターにのみを適用します。 この属性は、トークン以外のパラメーター、反復子以外のメソッド、他の型を返すメソッドなど、他のコンテキストには影響しません。

[EnumeratorCancellation]属性を 1 つの CancellationToken パラメーター (CS8425) に追加します。 この属性がないと、呼び出し元が WithCancellation を介して提供されたトークンは反復子本体に転送されません。 生成された GetAsyncEnumerator(CancellationToken) パラメーターは使用されません。

複数ではなく 1 つのパラメーターにのみ属性を適用します (CS8426)。 ランタイム インフラストラクチャでは、反復子への単一のキャンセル トークンの転送がサポートされています。 複数のトークン パラメーターがある場合は、属性を持つ 1 つだけを指定し、 CreateLinkedTokenSource(CancellationToken, CancellationToken)を使用して他のパラメーターを手動で結合します。