どのタイプのクラスがforeach
ループを使用できますか?
7 に答える
実際、厳密に言えば、使用する必要があるのは、メソッドとプロパティを持つものを返すforeach
パブリックメソッドだけです。ただし、これの最も一般的な意味は、「 /を実装し、 /を返すもの」です。GetEnumerator()
bool MoveNext()
? Current {get;}
IEnumerable
IEnumerable<T>
IEnumerator
IEnumerator<T>
含意によって、これには、、、配列()などのような/を実装するものすべてが含まれます。したがってICollection
、標準の「データのコレクション」は通常、をサポートします。ICollection<T>
Collection<T>
List<T>
T[]
foreach
最初のポイントを証明するために、以下は問題なく機能します。
using System;
class Foo {
public int Current { get; private set; }
private int step;
public bool MoveNext() {
if (step >= 5) return false;
Current = step++;
return true;
}
}
class Bar {
public Foo GetEnumerator() { return new Foo(); }
}
static class Program {
static void Main() {
Bar bar = new Bar();
foreach (int item in bar) {
Console.WriteLine(item);
}
}
}
それはどのように機能しますか?
foreach(int i in obj) {...}
ちょっとのようなforeachループは次のようになります。
var tmp = obj.GetEnumerator();
int i; // up to C# 4.0
while(tmp.MoveNext()) {
int i; // C# 5.0
i = tmp.Current;
{...} // your code
}
ただし、バリエーションがあります。たとえば、列挙子(tmp)がをサポートしIDisposable
ている場合は、それも使用されます(と同様using
)。
ループの内側(C#5.0)と外側(C#4.0まで)の宣言" int i
"の配置の違いに注意してください。コードブロック内で匿名メソッド/ラムダで使用する場合は重要です。しかし、それは別の話です;-pi
MSDNから:
このステートメントは、配列またはオブジェクトコレクション
foreach
内の要素ごとに埋め込みステートメントのグループを繰り返します。このステートメントは、コレクションを反復処理して目的の情報を取得するために使用されますが、予期しない副作用を回避するためにコレクションの内容を変更するために使用しないでください。(私の強調)foreach
したがって、配列がある場合は、次のようにforeachステートメントを使用して配列を反復処理できます。
int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
foreach (int i in fibarray)
{
System.Console.WriteLine(i);
}
List<T>
次のように、コレクションを反復処理するためにも使用できます。
List<string> list = new List<string>();
foreach (string item in list)
{
Console.WriteLine(item);
}
ブログ投稿Duck Notationによると、ダックタイピングが使用されています。
ドキュメントは次のとおりです。 主な記事 With Arrays With Collection Objects
「コレクション要素の型は識別子型に変換可能でなければならない」ことに注意することが重要です。これは、コンパイル時にチェックできない場合があり、インスタンス型が参照型に割り当てられない場合、実行時例外が生成される可能性があります。
オレンジなど、フルーツ バスケットに Apple 以外のものがある場合、実行時例外が生成されます。
List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)
これは、 Enumerable.OfTypeを使用してリストを Apple のみに安全にフィルタリングします。
foreach(Apple a in fruitBasket.OfType<Apple>() )