Wie kann ich eine Liste <T> durchlaufen und jedes Element abrufen?

176

Wie kann ich eine Liste durchlaufen und jedes Element abrufen?

Ich möchte, dass die Ausgabe folgendermaßen aussieht:

Console.WriteLine("amount is {0}, and type is {1}", myMoney.amount, myMoney.type);

Hier ist mein Code:

static void Main(string[] args)
{
    List<Money> myMoney = new List<Money> 
    {
        new Money{amount = 10, type = "US"},
        new Money{amount = 20, type = "US"}
    };
}

class Money
{
    public int amount { get; set; }
    public string type { get; set; }
}
user1929393
quelle

Antworten:

274

foreach::

foreach (var money in myMoney) {
    Console.WriteLine("Amount is {0} and type is {1}", money.amount, money.type);
}

MSDN Link

Da es sich um eine List<T>.. handelt, die eine Indexermethode implementiert [], können Sie alternativ auch eine normale forSchleife verwenden .. obwohl sie weniger lesbar ist (IMO):

for (var i = 0; i < myMoney.Count; i++) {
    Console.WriteLine("Amount is {0} and type is {1}", myMoney[i].amount, myMoney[i].type);
}
Simon Whitehead
quelle
7
@awudoin Was? Nein, tut es nicht. Es erstellt eine Referenz auf dem Stapel. Ansonsten nicht. A foreachklont die Objekte nicht ..
Simon Whitehead
2
Ich sollte klarstellen: Es wird auch ein Enumerator.. erstellt, das ein struct.. ist, das sich ebenfalls auf dem Stapel befindet. Ich verstehe also immer noch nicht ganz, worauf Sie mit Ihrem Kommentar gekommen sind.
Simon Whitehead
7
Du hast recht ... es ist nur eine Enumeratorund keine Kopie des Objekts. Aber die Tatsache bleibt, je nachdem, was Sie tun, gibt es mehr Overhead mit einer foreachSchleife als mit einer forSchleife. Ich habe gerade einen Schnelltest mit Ihrem Code mit 100.000 Einträgen in der durchgeführt Listund die foreachSchleife hat doppelt so lange gedauert (tatsächlich 1,9-mal so lange). Dies gilt nicht unbedingt in allen Situationen, aber in vielen. Es hängt von der Größe der Liste ab, wie viele Operationen Sie innerhalb der Schleife ausführen usw. Dies war das, worauf ich hinaus wollte.
Awudoin
36

Der Vollständigkeit halber gibt es auch den LINQ / Lambda-Weg:

myMoney.ForEach((theMoney) => Console.WriteLine("amount is {0}, and type is {1}", theMoney.amount, theMoney.type));
Acarlon
quelle
20

Genau wie jede andere Sammlung. Mit der Hinzufügung der List<T>.ForEachMethode.

foreach (var item in myMoney)
    Console.WriteLine("amount is {0}, and type is {1}", item.amount, item.type);

for (int i = 0; i < myMoney.Count; i++)
    Console.WriteLine("amount is {0}, and type is {1}", myMoney[i].amount, myMoney[i].type);

myMoney.ForEach(item => Console.WriteLine("amount is {0}, and type is {1}", item.amount, item.type));
Khan
quelle
6
Ein weiteres Wort der Warnung: Wenn Sie eine große Liste haben (mit "groß" meine ich über 100.000 Elemente), dauert myMoney.Count eine Weile, da es die Liste durchlaufen muss, um die Zählung durchzuführen, und in den Beispielen über myMoney. Die Anzahl wird jedes Mal in der Schleife gezählt. Verwenden Sie also int myMoneyC = myMoney.Count; for (int i = 0; i <myMoneyC; i ++) beschleunigt diese Schleife um ein Vielfaches.
SuperGSJ
12

So würde ich mit mehr schreiben functional way. Hier ist der Code:

new List<Money>()
{
     new Money() { Amount = 10, Type = "US"},
     new Money() { Amount = 20, Type = "US"}
}
.ForEach(money =>
{
    Console.WriteLine($"amount is {money.Amount}, and type is {money.Type}");
});
Codierer Absolut
quelle
2
Vielen Dank. Dies ist ein sehr kurzer Weg, um diese Aufgabe zu erfüllen. Sie haben auch die neue und kompakte Syntax von writeLine verwendet, die in VS 2017 / .NET 4.7 eingeführt wurde.
Deep