Wie funktionieren foreach-Schleifen in C #? [geschlossen]

85

Welche Arten von Klassen können foreachSchleifen verwenden?

user48616
quelle
5
Möglicherweise möchten Sie eine andere akzeptierte Antwort auswählen, da die von Ihnen ausgewählte Antwort nicht wirklich repräsentativ für die richtige Antwort ist.
George Stocker

Antworten:

162

Eigentlich streng genommen alles , was Sie verwenden müssen , foreachist eine öffentliche GetEnumerator()Methode , dass die Renditen etwas mit einem bool MoveNext()Verfahren und einer ? Current {get;}Eigenschaft. Die häufigste Bedeutung davon ist jedoch "etwas, das IEnumerable/ implementiert IEnumerable<T>und ein IEnumerator/ zurückgibt IEnumerator<T>.

Implizit enthält dies etwas , dass Geräte ICollection/ ICollection<T>, wie etwas Collection<T>, List<T>Arrays ( T[]) usw. Also jeden Standard „Sammlung von Daten“ wird im Allgemeinen unterstützen foreach.

Zum Beweis des ersten Punktes funktioniert Folgendes einwandfrei:

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

Wie funktioniert es?

Eine foreach-Schleife wie foreach(int i in obj) {...}folgt:

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

Es gibt jedoch Variationen. Wenn es beispielsweise vom Enumerator (tmp) unterstützt wird IDisposable, wird es auch verwendet (ähnlich wie using).

Beachten Sie den Unterschied in der Platzierung der Deklaration " int i" innerhalb (C # 5.0) gegenüber außerhalb (bis C # 4.0) der Schleife. Es ist wichtig, wenn Sie ieine anonyme Methode / Lambda in Ihrem Codeblock verwenden. Aber das ist eine andere Geschichte ;-p

Marc Gravell
quelle
3
+1 für die Tiefe. Normalerweise gehe ich nicht so ausführlich auf eine Frage ein, die möglicherweise eine Anfängerfrage ist, da sie für den neuen Programmierer überwältigend erscheint.
George Stocker
Stimmt, Gortok - also habe ich das Zeug über Listen / Arrays / etc.
Marc Gravell
Es wäre gut, das implizite Laufzeit-Casting in die Schleifenvariable zu erwähnen - kann zu Ausnahmen bei der Typinkompatibilität führen.
Daniel Earwicker
3
Vergessen Sie nicht: Wenn Sie ein Array mit foreach verwenden, erstellt der Compiler ein einfaches for-loop(Sie können dies sehen, wenn Sie mit IL arbeiten).
Felix K.
1
@ Marc Gravell: OK, cool! Ich habe den Beitrag bearbeitet, um ihn klarer zu machen - zumindest für mich. Schließlich ist die Platzierung nicht nur in C # 5.0 wichtig, sondern immer wichtig, nur dass sie sich geändert hat. Ich hoffe es macht dir nichts aus.
Paul Groke
7

Von MSDN :

Die foreachAnweisung wiederholt eine Gruppe eingebetteter Anweisungen für jedes Element in einem Array oder einer Objektsammlung . Die foreachAnweisung wird verwendet, um die Sammlung zu durchlaufen, um die gewünschten Informationen zu erhalten. Sie sollte jedoch nicht verwendet werden, um den Inhalt der Sammlung zu ändern, um unvorhersehbare Nebenwirkungen zu vermeiden. (Hervorhebung von mir)

Wenn Sie also ein Array haben, können Sie die foreach-Anweisung verwenden, um das Array wie folgt zu durchlaufen:

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

Sie können es auch verwenden, um eine List<T>Sammlung zu durchlaufen , wie folgt :

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

foreach (string item in list)
{
    Console.WriteLine(item);
}
George Stocker
quelle
4
Seltsamerweise müssen Objekttypen laut MSDN ( msdn.microsoft.com/en-us/library/9yb8xew9(VS.80).aspx ) IEnumerable nicht implementieren. Jeder Typ, der GetEnumerator, MoveNext, Reset und Current auf die richtige Weise definiert. Seltsam, oder?
Sean Reilly
Ordentlich. Das wusste ich nicht. :-)
George Stocker
2

Hier sind die Dokumente: Hauptartikel mit Arrays mit Sammlungsobjekten

Es ist wichtig zu beachten, dass "Der Typ des Auflistungselements muss in den Bezeichnertyp konvertierbar sein". Dies kann manchmal nicht zur Kompilierungszeit überprüft werden und kann eine Laufzeitausnahme generieren, wenn der Instanztyp nicht dem Referenztyp zugewiesen werden kann.

Dies generiert eine Laufzeitausnahme, wenn sich ein Nicht-Apfel im Obstkorb befindet, z. B. eine Orange.

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

Dadurch wird die Liste mit Enumerable.OfType sicher nur nach Äpfeln gefiltert

foreach(Apple a in fruitBasket.OfType<Apple>() )
Amy B.
quelle
-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);
    }
}
Shahzad
quelle
-1

Nützliche Informationen zu diesem Thema finden Sie auch auf MSDN . Nehmen Sie die Essenz aus diesem Artikel:

Das Schlüsselwort foreach listet eine Sammlung auf und führt die eingebettete Anweisung einmal für jedes Element in der Sammlung aus:

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

Der Compiler übersetzt die im obigen Beispiel gezeigte foreach-Schleife in etwas Ähnliches wie dieses Konstrukt:

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

Sie können dies versuchen ...

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