Bagaimana foreach loop bekerja di C #? [Tutup]


86

Jenis kelas apa yang dapat menggunakan foreachloop?


5
Anda mungkin ingin memilih jawaban yang diterima berbeda, karena yang Anda pilih tidak benar-benar mewakili jawaban yang benar.
George Stocker

Jawaban:


162

Sebenarnya, tegasnya , yang Anda perlukan foreachhanyalah GetEnumerator()metode publik yang mengembalikan sesuatu dengan bool MoveNext()metode dan ? Current {get;}properti. Namun, arti paling umum dari ini adalah "sesuatu yang mengimplementasikan IEnumerable/ IEnumerable<T>, mengembalikan IEnumerator/ IEnumerator<T>.

Implikasinya, ini termasuk apa saja yang mengimplementasikan ICollection/ ICollection<T>, seperti sesuatu seperti Collection<T>, List<T>, array ( T[]), dll Jadi setiap "pengumpulan data" standar akan umumnya mendukung foreach.

Untuk bukti poin pertama, berikut ini berfungsi dengan baik:

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

Bagaimana cara kerjanya?

Sebuah loop foreach seperti foreach(int i in obj) {...}agak sama dengan:

var tmp = obj.GetEnumerator();
int i; // up to C# 4.0
while(tmp.MoveNext()) {
    int i; // C# 5.0
    i = tmp.Current;
    {...} // your code
}

Namun, ada variasi. Misalnya, jika enumerator (tmp) mendukung IDisposable, maka digunakan juga (mirip dengan using).

Perhatikan perbedaan penempatan deklarasi " int i" di dalam (C # 5.0) vs. di luar (up C # 4.0) loop. Ini penting jika Anda menggunakan imetode anonim / lambda di dalam blok kode Anda. Tapi itu cerita lain ;-p


3
1 untuk mendalami. Saya biasanya tidak membahasnya secara mendalam untuk pertanyaan yang mungkin merupakan pertanyaan 'pemula' karena akan tampak berlebihan bagi programmer baru.
George Stocker

Benar, Gortok - jadi saya menindaklanjuti dengan hal-hal tentang daftar / array / dll.
Marc Gravell

Akan lebih baik untuk menyebutkan casting runtime implisit ke variabel loop - dapat menghasilkan pengecualian ketidakcocokan tipe.
Daniel Earwicker

3
Jangan lupa: Saat menggunakan array dengan foreach, kompilator membuat sederhana for-loop(Anda dapat melihat ini saat bekerja dengan IL).
Felix K.

1
@Marc Gravell: Oke, keren! Saya mengedit posting untuk membuatnya lebih jelas - setidaknya bagi saya. Bagaimanapun penempatan tidak hanya penting di C # 5.0, itu selalu penting, hanya saja itu berubah. Saya harap Anda tidak keberatan.
Paul Groke

7

Dari MSDN :

The foreachPernyataan mengulangi sekelompok pernyataan tertanam untuk setiap elemen dalam array atau koleksi objek . The foreachpernyataan digunakan untuk iterate melalui koleksi untuk mendapatkan informasi yang diinginkan, tetapi tidak boleh digunakan untuk mengubah isi dari koleksi untuk menghindari efek samping tak terduga. (penekanan saya)

Jadi, jika Anda memiliki sebuah array, Anda bisa menggunakan pernyataan foreach untuk melakukan iterasi melalui array tersebut, seperti:

 int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
    foreach (int i in fibarray)
    {
        System.Console.WriteLine(i);
    }

Anda juga bisa menggunakannya untuk mengulang melalui List<T>koleksi, seperti:

List<string> list = new List<string>();

foreach (string item in list)
{
    Console.WriteLine(item);
}

4
anehnya, menurut MSDN ( msdn.microsoft.com/en-us/library/9yb8xew9(VS.80).aspx ), jenis objek tidak perlu mengimplementasikan IEnumerable. Semua jenis yang mendefinisikan GetEnumerator, MoveNext, Reset dan Current dengan cara yang benar akan bekerja. Aneh, ya?
Sean Reilly

Rapi. Saya tidak tahu itu. :-)
George Stocker


2

Berikut dokumentasinya: Artikel utama Dengan Array Dengan Objek Koleksi

Penting untuk diperhatikan bahwa "Jenis elemen koleksi harus dapat diubah menjadi jenis pengenal". Terkadang hal ini tidak dapat diperiksa pada waktu kompilasi dan dapat menghasilkan pengecualian waktu proses jika jenis instance tidak dapat ditetapkan ke jenis referensi.

Ini akan menghasilkan pengecualian waktu proses jika ada non-Apple di keranjang buah, seperti jeruk.

List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)

Ini dengan aman memfilter daftar hanya ke Apel menggunakan Enumerable.OfType

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

Info yang berguna tentang subjek ini dapat ditemukan di MSDN juga. Mengambil inti dari artikel itu:

Kata kunci foreach menghitung koleksi, mengeksekusi pernyataan yang disematkan satu kali untuk setiap elemen dalam koleksi:

foreach (var item in collection)
{
    Console.WriteLine(item.ToString());
}

Kompilator menerjemahkan loop foreach yang ditunjukkan pada contoh di atas menjadi sesuatu yang mirip dengan konstruksi ini:

IEnumerator<int> enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
    var item = enumerator.Current;
    Console.WriteLine(item.ToString());
}

-2

Anda dapat mencoba ini ...

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);
        }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.