C#コンパイラ エラー CS0202の原因と対処法について解説
CS0202 エラーは、foreach で利用するための GetEnumerator
メソッドが、不適切な型(public な MoveNextメソッドや Currentプロパティを含まない型)を返す場合に発生します。
配列やポインターは利用できず、正しく反復処理できる列挙子を実装する必要があります。
C# 2.0以降では、ジェネリック対応により自動生成が行われるため、正しい実装が求められます。
CS0202エラーの原因
foreachステートメントの基本動作と列挙子の要件
MoveNextメソッドの役割と仕様
foreachステートメントでは、反復処理を実行する際に列挙子のMoveNext
メソッドが呼び出されます。
MoveNext
メソッドは、内部で保持するコレクションの位置を次に進め、次の要素が存在するかをbool
型で返す機能を持っています。
これは、繰り返し処理が終了すべきタイミングを判断するための重要なメソッドです。
たとえば、コレクション内で要素がなくなった場合、MoveNext
がfalse
を返すことでループが終了します。
Currentプロパティの定義と使い方
foreach文では、列挙子のCurrent
プロパティを通じて、現在の要素にアクセスします。
Current
プロパティはpublicに定義され、コレクション内の現在位置にある値を返す役割があります。
もしこのプロパティが正しく実装されていない、もしくはアクセス修飾子が不適切である場合、foreach文は正しく動作せず、エラーCS0202が発生するリスクがあります。
適切な実装により、foreachでの要素取得が円滑に行われるようになります。
GetEnumeratorメソッド実装の問題点
不適切な返り値(配列やポインター)のリスク
foreachステートメントは、対象のオブジェクトに対してGetEnumerator
メソッドを呼び出し、その返り値が列挙子としての要件(publicなMoveNext
メソッドとCurrent
プロパティを持つ)を満たしているかを確認します。
もしGetEnumerator
が配列やポインターを返す場合、これらには必要なメソッドやプロパティが存在しないため、CS0202エラーが発生してしまいます。
返り値の型は、列挙子として機能するクラスのインスタンスである必要があるため、実装の際は注意が必要です。
CS0202エラーの対処法
列挙子クラスの正しい実装方法
クラス設計における返り値の修正ポイント
返り値として返すオブジェクトは、必ず列挙子として必要な機能、すなわちpublicなMoveNext
メソッドとCurrent
プロパティが含まれていることを確認する必要があります。
たとえば、間違って配列などを返してしまうと、foreach文で必要なメソッドが見つからず、CS0202エラーが発生します。
列挙子を実装する際は、正しいクラス設計を行い、返り値の型を明確に指定することが重要です。
正しいMoveNextとCurrentの実装
正しい実装例として、内部に配列を持ち、その配列を順番に返す列挙子クラスを作成する方法があります。
以下のサンプルコードは、SampleEnumerator
クラスにおいて、MoveNext
メソッドとCurrent
プロパティがどのように実装されるかを示しています。
using System;
using System.Collections;
using System.Collections.Generic;
// 列挙子クラスの実装
public class SampleEnumerator : IEnumerator<int>
{
private int[] numbers = new int[] { 10, 20, 30 }; // サンプルの数値データ
private int position = -1; // 現在位置
public int Current
{
get
{
// 現在位置の要素を返す
return numbers[position];
}
}
// 非ジェネリックなIEnumeratorの実装
object IEnumerator.Current => Current;
public bool MoveNext()
{
// 次の要素へ移動、存在する場合はtrueを返す
position++;
return position < numbers.Length;
}
public void Reset()
{
// 現在位置をリセットする
position = -1;
}
public void Dispose() { }
}
// IEnumerableインターフェイスを実装したコレクションクラス
public class SampleCollection : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
return new SampleEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Program
{
public static void Main()
{
SampleCollection collection = new SampleCollection();
foreach(int number in collection)
{
Console.WriteLine(number);
}
}
}
10
20
30
foreachステートメント利用時の修正手順
コード例に基づく実装見直しポイント
foreachステートメントを利用する際にまず確認すべきは、GetEnumerator
メソッドが正しい列挙子オブジェクトを返しているかという点です。
返されるオブジェクトに対して、必ずMoveNext
メソッドとCurrent
プロパティが適切に実装されているかチェックします。
もし問題が発見された場合は、実装の誤り、たとえば配列やポインターが返却されていないか、正しいクラスのインスタンスが返されているかを重点的に見直す必要があります。
具体的なコード例をもとに、一度実装内容を再確認することで、エラーの原因を特定しやすくなります。
C#バージョンによる自動生成仕様の確認
C# 2.0以前のバージョンでは、コンパイラがMoveNext
およびCurrent
の実装を自動生成する場合がありました。
しかし、最新のC#バージョンでは、正確な実装を要求されるため、過去の自動生成仕様に依存するとエラーが発生する可能性が高くなります。
特にジェネリックインターフェイスの導入以降は、列挙子クラスとして必要な仕様が明示的になっているため、実装時には使用中のC#バージョンの仕様を確認しながらコードを見直すことが大切です。
まとめ
この記事では、C#のforeach文で発生するCS0202エラーの原因として、列挙子に必要なpublicなMoveNextメソッドとCurrentプロパティが実装されていなかったり、GetEnumeratorメソッドが不適切な返り値(配列やポインター)を返すケースがある点を解説しました。
また、正しい列挙子クラスの設計方法や実装例も示し、foreach文使用時の修正ポイントとC#バージョンによる仕様の違いに注意する必要性を説明しています。