Jak mogę przejrzeć List <T> i pobrać każdy element?

176

Jak mogę przejrzeć listę i złapać każdy przedmiot?

Chcę, aby wynik wyglądał następująco:

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

Oto mój kod:

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
źródło

Odpowiedzi:

274

foreach:

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

MSDN Link

Alternatywnie, ponieważ jest to List<T>.. implementująca metodę indeksatora [], możesz również użyć normalnej forpętli .. chociaż jest mniej czytelna (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
źródło
7
@awudoin What? Nie, nie robi… tworzy odniesienie na stosie… poza tym nie robi. A foreachnie klonuje obiektów ...
Simon Whitehead,
2
Powinienem wyjaśnić: Tworzy również Enumerator.., który jest struct.., który również znajduje się na stosie. Więc nadal nie do końca rozumiem, o co ci chodzi w komentarzu.
Simon Whitehead
7
Masz rację… to tylko Enumeratorkopia, a nie kopia obiektu. Ale fakt pozostaje faktem, w zależności od tego, co robisz, foreachpętla jest bardziej obciążona niż forpętla. Właśnie przeprowadziłem szybki test z twoim kodem ze 100 000 wpisów w pętli, Lista foreachpętla trwała dwa razy dłużej (właściwie 1,9 razy dłużej). Nie zawsze jest to prawdą we wszystkich sytuacjach, ale w wielu. Zależy to od rozmiaru listy, liczby operacji wykonywanych w pętli, itp.… Właśnie o to mi chodziło.
awudoin
36

Dla kompletności istnieje również sposób LINQ / Lambda:

myMoney.ForEach((theMoney) => Console.WriteLine("amount is {0}, and type is {1}", theMoney.amount, theMoney.type));
akarlon
źródło
20

Jak każda inna kolekcja. Z dodatkiem List<T>.ForEachmetody.

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));
Chan
źródło
6
Kolejne słowo ostrzeżenia, jeśli masz dużą listę (przez dużą mam na myśli ponad 100 000 pozycji) myMoney.Count zaczyna zająć trochę czasu, ponieważ musi przejść przez listę, aby wykonać zliczanie, w przykładach powyżej myMoney. Licznik jest liczony za każdym razem wokół pętli. Więc używając int myMoneyC = myMoney.Count; for (int i = 0; i <myMoneyC; i ++) sprawi, że ta pętla będzie wielokrotnie szybsza.
SuperGSJ
12

Tak napisałbym używając więcej functional way. Oto kod:

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}");
});
Coder Absolute
źródło
2
Dzięki. To bardzo krótka droga do wykonania tego zadania. Użyto również nowej i kompaktowej składni writeLine, która została wprowadzona w VS 2017 / .NET 4.7.
Głęboki