どのタイプのクラスがforeach
ループを使用できますか?
回答:
実際、厳密に言えば、使用する必要があるのは、メソッドとプロパティを持つものを返す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
for-loop
(ILを使用しているときにこれを確認できます)。
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);
}
ブログ投稿DuckNotationによると、ダックタイピングが使用されています。
ドキュメントは次のとおりです。 コレクションオブジェクトを含む配列を使用した主な記事
「コレクション要素のタイプは識別子タイプに変換可能でなければならない」ことに注意することが重要です。これはコンパイル時にチェックできない場合があり、インスタンスタイプが参照タイプに割り当てられない場合、ランタイム例外が生成される可能性があります。
オレンジなど、フルーツバスケットに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>() )
IList<ListItem> illi = new List<ListItem>();
ListItem li = null;
foreach (HroCategory value in listddlsubcategory)
{
listddlsubcategoryext = server.getObjectListByColumn(typeof(HroCategory), "Parentid", value.Id);
li = new ListItem();
li.Text = value.Description;
li.Value = value.Id.ToString();
illi.Add(li);
IList<ListItem> newilli = new List<ListItem>();
newilli = SubCatagoryFunction(listddlsubcategoryext, "-->");
foreach (ListItem c in newilli)
{
illi.Add(c);
}
}
この主題に関する有用な情報は、MSDNにもあります。その記事から本質をとる:
foreachキーワードはコレクションを列挙し、コレクション内の要素ごとに埋め込みステートメントを1回実行します。
foreach (var item in collection)
{
Console.WriteLine(item.ToString());
}
コンパイラーは、上記の例に示されているforeachループを次の構成に類似したものに変換します。
IEnumerator<int> enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
var item = enumerator.Current;
Console.WriteLine(item.ToString());
}