foreachループはC#でどのように機能しますか?[閉まっている]


86

どのタイプのクラスがforeachループを使用できますか?


5
選択した回答は実際には正解を表していないため、別の受け入れられた回答を選択することをお勧めします。
ジョージストッカー

回答:


162

実際、厳密に言えば、使用する必要があるのは、メソッドとプロパティを持つものを返すforeachパブリックGetEnumerator()メソッドだけです。しかし、最も一般的なこの意味は、「実装がいることを何かである/ 、返す/を。bool MoveNext()? Current {get;}IEnumerableIEnumerable<T>IEnumeratorIEnumerator<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


3
深く掘り下げるための+1。私は通常、「初心者」の質問である可能性のある質問については、新しいプログラマーには圧倒されるように思われるので、それほど深くは説明しません。
ジョージストッカー

確かに、Gortok-だから私はリスト/配列などに関するものをフォローアップしました。
MarcGravell

ループ変数への暗黙的なランタイムキャストについて言及するとよいでしょう-型の非互換性の例外が発生する可能性があります。
Daniel Earwicker 2009

3
忘れないでください:foreachで配列を使用すると、コンパイラーは単純なものを作成しますfor-loop(ILを使用しているときにこれを確認できます)。
Felix K.

1
@Marc Gravell:OK、かっこいい!少なくとも私にとっては、投稿を編集してわかりやすくしました。結局のところ、配置はC#5.0で重要であるだけでなく、変更されたことだけが常に重要です。よろしくお願いします。
Paul Groke 2013

7

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);
}

4
奇妙なことに、MSDN(msdn.microsoft.com/en-us/library/9yb8xew9VS.80.aspx)によると、オブジェクトタイプはIEnumerableを実装する必要はありません。GetEnumerator、MoveNext、Reset、Currentを正しい方法で定義するタイプはすべて機能します。変だよね?
ショーンライリー

きちんとした。私はそれを知りませんでした。:-)
ジョージストッカー


2

ドキュメントは次のとおりです。 コレクションオブジェクトを含む配列を使用した主な記事

「コレクション要素のタイプは識別子タイプに変換可能でなければならない」ことに注意することが重要です。これはコンパイル時にチェックできない場合があり、インスタンスタイプが参照タイプに割り当てられない場合、ランタイム例外が生成される可能性があります。

オレンジなど、フルーツバスケットに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>() )

-1
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);
    }
}

-1

この主題に関する有用な情報は、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());
}

-2

あなたはこれを試すことができます...

List<int> numbers = new List<int>();
        numbers.Add(5);
        numbers.Add(15);
        numbers.Add(25);
        numbers.Add(35);

        Console.WriteLine("You are added total number: {0}",numbers.Count);
        foreach (int number in numbers)
        {
            Console.WriteLine("Your adding Number are: {0}", number);
        }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.