In.NET, która pętla działa szybciej, " for " czy "foreach"?

W C# / VB. NET/. net, która pętla działa szybciej, for Czy foreach?

Odkąd przeczytałem, że pętla for działa szybciej niż pętla foreachpętla a dawno temu założyłem, że jest prawdziwa dla wszystkich zbiorów, zbiorów ogólnych, wszystkich tablic itp.

Przeszukałem Google i znalazłem kilka artykułów, ale większość z nich jest niejednoznaczna (czytaj komentarze do artykułów) i otwarta.

Ideałem byłoby, aby każdy scenariusz był wymieniony i najlepszy rozwiązanie dla tego samego.

Na przykład (tylko przykład jak powinno być):

  1. do iteracji tablicy 1000+ strings - for is better than foreach
  2. dla iteracji nad IList (non generic) łańcuchami - foreach jest lepsze than for

Kilka odniesień znalezionych w sieci dla tego samego:

  1. oryginalny wielki stary artykuł Emmanuela Schanzera
  2. CodeProject FOREACH Vs. FOR
  3. Blog-Do foreach lub nie foreach, Oto jest pytanie
  4. ASP.NET forum-NET 1.1 c # for vs foreach

[Edytuj]

Poza aspektem czytelności, bardzo interesują mnie fakty i liczby. Istnieją aplikacje, w których ostatnia mila optymalizacji wydajności ma znaczenie.

Author: Binoj Antony, 2008-12-13

30 answers

Patrick Smacchia napisał o tym w zeszłym miesiącu, z następującymi wnioskami:

  • dla pętli na liście są nieco ponad 2 razy tańsze niż foreach pętle na liście.
  • zapętlenie tablicy jest około 2 razy tańsze niż zapętlenie listy.
  • w konsekwencji zapętlenie tablicy za pomocą for jest 5 razy tańsze niż zapętlenie listy za pomocą foreach (co, jak sądzę, jest tym, co wszyscy robimy).
 382
Author: Ian Nelson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-13 20:19:54

Po pierwsze, powództwo przeciwne do odpowiedzi Dmitry ' ego (teraz usuniętej) . W przypadku tablic kompilator C# emituje w dużej mierze ten sam kod dla foreach, co dla równoważnej pętli for. To wyjaśnia, dlaczego dla tego benchmarka wyniki są zasadniczo takie same: {]}

using System;
using System.Diagnostics;
using System.Linq;

class Test
{
    const int Size = 1000000;
    const int Iterations = 10000;

    static void Main()
    {
        double[] data = new double[Size];
        Random rng = new Random();
        for (int i=0; i < data.Length; i++)
        {
            data[i] = rng.NextDouble();
        }

        double correctSum = data.Sum();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j=0; j < data.Length; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in data)
            {
                sum += d;
            }
            if (Math.Abs(sum-correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop: {0}", sw.ElapsedMilliseconds);
    }
}

Wyniki:

For loop: 16638
Foreach loop: 16529

Następnie sprawdzamy, czy punkt Grega o typie zbioru jest ważny-Zmień tablicę na List<double> w powyższym punkcie, a otrzymasz radykalnie różne wyniki. Nie tylko jest znacznie wolniejszy ogólnie rzecz biorąc, ale foreach staje się znacznie wolniejszy niż dostęp przez indeks. Mimo to nadal prawie zawsze wolę pętlę for niż pętlę for, w której to kod jest prostszy - ponieważ czytelność jest prawie zawsze ważna, podczas gdy mikro-optymalizacja rzadko jest.

 170
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-11 18:27:17

foreach pętle wykazują bardziej konkretne intencje niż pętle for .

Użycie pętli foreach pokazuje każdemu, kto używa Twojego kodu, że planujesz zrobić coś z każdym członkiem kolekcji, niezależnie od jego miejsca w kolekcji. Pokazuje również, że nie modyfikujesz oryginalnej kolekcji (i rzuca wyjątek, jeśli spróbujesz).

Drugą zaletą foreach jest to, że działa na dowolnym IEnumerable, gdzie jako for ma sens tylko dla IList, gdzie każdy element faktycznie ma indeks.

Jeśli jednak potrzebujesz użyć indeksu elementu, to oczywiście powinieneś mieć możliwość użycia pętli for. Ale jeśli nie musisz używać indeksu, posiadanie go jest po prostu zaśmiecaniem kodu.

Nie ma znaczących implikacji wydajności, o ile mi wiadomo. Na pewnym etapie w przyszłości może być łatwiej zaadaptować kod za pomocą foreach do uruchamiania na wielu rdzeniach, ale nie jest to teraz powód do zmartwień.

 162
Author: ctford,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-04 12:56:54

Za każdym razem, gdy pojawią się argumenty dotyczące wydajności, wystarczy napisać mały test, aby móc wykorzystać wyniki ilościowe do wsparcia swojej sprawy.

Użyj klasy stopera i powtórz coś kilka milionów razy, dla dokładności. (To może być trudne bez pętli for):

using System.Diagnostics;
//...
Stopwatch sw = new Stopwatch()
sw.Start()
for(int i = 0; i < 1000000;i ++)
{
    //do whatever it is you need to time
}
sw.Stop();
//print out sw.ElapsedMilliseconds

Trzymamy kciuki za wyniki tego pokazania, że różnica jest znikoma i równie dobrze możesz zrobić to, co przyniesie najbardziej możliwy do utrzymania kod

 53
Author: Rob Fonseca-Ensor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-22 21:21:57

Zawsze będzie blisko. Dla tablicy czasami for jest nieco szybszy, ale foreach jest bardziej wyrazisty i oferuje LINQ itp. Ogólnie rzecz biorąc, trzymaj się foreach.

Dodatkowo, foreach może być zoptymalizowany w niektórych scenariuszach. Na przykład, lista połączona może być straszna przez indekser, ale może być szybka przez foreach. W rzeczywistości standard LinkedList<T> nie oferuje nawet indeksatora z tego powodu.

 50
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-13 17:46:25

Zgaduję, że prawdopodobnie nie będzie to istotne w 99% przypadków, więc dlaczego miałbyś wybrać szybszy zamiast najbardziej odpowiedni(jak w najprostszym do zrozumienia/utrzymania)?

 36
Author: Brian Rasmussen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-13 19:51:41

Jest mało prawdopodobne, aby istniała między nimi ogromna różnica w wydajności. Jak zawsze, w obliczu " co jest szybsze?"pytanie, zawsze powinieneś myśleć, że mogę to zmierzyć."

Napisz dwie pętle, które robią to samo w ciele pętli, wykonaj je i zmierz czas i zobacz jaka jest różnica prędkości. Zrób to zarówno z prawie pustym ciałem, jak i ciałem pętli podobnym do tego, co faktycznie będziesz robił. Spróbuj również z typem kolekcji, którego używasz, ponieważ różne rodzaje kolekcji mogą mieć różne właściwości użytkowe.

 32
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-23 07:36:03

Są bardzo dobre powody, aby preferować foreach loops over for loops. Jeśli możesz użyć pętli foreach, twój szef ma rację, że powinieneś.

Jednak nie każda iteracja po prostu przechodzi przez Listę po kolei. Jeśli on jest zakazuje dla, tak, to jest złe.

Na Twoim miejscu zrobiłbym przekształcenie wszystkich twoich naturalnych pętli w rekurencję . To by go nauczyło, i to jest również dobre ćwiczenie umysłowe dla Ciebie.

 32
Author: T.E.D.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-22 16:17:13

Jeffrey Richter na TechEd 2005:

" przez lata nauczyłem się, że kompilator C# jest dla mnie w zasadzie kłamcą." .. "Kłamie o wielu rzeczach." .. "Jak wtedy, gdy robisz pętlę foreach..." .. "...to jest jedna mała linijka kodu, którą piszesz, ale to, co kompilator C# wypluwa, aby to zrobić, jest fenomenalne. Wyrzuca tam try / finally block, wewnątrz finally block wrzuca zmienną do IDisposable interface, a jeśli cast się powiedzie, wywoła Dispose Metoda na nim, wewnątrz pętli wywołuje bieżącą właściwość i MoveNext metoda wielokrotnie wewnątrz pętli, obiekty są tworzone pod pokrywami. Wiele osób używa foreach, ponieważ jest to bardzo łatwe kodowanie, bardzo łatwe do zrobienia.." .. "foreach nie jest zbyt dobry pod względem wydajności, jeśli iterację nad kolekcją zamiast za pomocą notacji nawiasów kwadratowych, po prostu robi Indeks, to po prostu znacznie szybciej i nie tworzy żadnych obiektów na stercie..."

On-Demand Webcast: http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032292286&EventCategory=3&culture=en-US&CountryCode=US

 18
Author: Max Toro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-03 15:38:08

To niedorzeczne. Nie ma przekonującego powodu, aby zakazać pętli for, wydajności lub innych.

Zobacz Jon Skeet ' s blog dla benchmark wydajności i innych argumentów.

 12
Author: Rik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 09:52:06

W przypadku, gdy pracujesz z kolekcją obiektów, foreach jest lepsza, ale jeśli zwiększysz liczbę, lepsza będzie pętla for.

Zauważ, że w ostatnim przypadku możesz zrobić coś takiego:

foreach (int i in Enumerable.Range(1, 10))...

Ale na pewno nie działa lepiej, w rzeczywistości ma gorszą wydajność w porównaniu do for.

 11
Author: Meta-Knight,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-05 08:14:35

To powinno cię uratować:

public IEnumerator<int> For(int start, int end, int step) {
    int n = start;
    while (n <= end) {
        yield n;
        n += step;
    }
}

Użycie:

foreach (int n in For(1, 200, 4)) {
    Console.WriteLine(n);
}

Dla większej wygranej, możesz wziąć trzech delegatów jako parametry.

 10
Author: akuhn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-13 18:04:36

Możesz o tym przeczytać w Deep. NET - Część 1 iteracja

Obejmuje wyniki (bez pierwszej inicjalizacji) z kodu źródłowego.NET aż do demontażu.

Na przykład - iteracja tablicy z pętlą foreach: Tutaj wpisz opis obrazka

And-list iteracja z pętlą foreach: Tutaj wpisz opis obrazka

I wyniki końcowe: Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

 10
Author: Or Yaacov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-24 12:02:46

Różnice prędkości w pętli for - i foreach - są niewielkie, gdy przechodzisz przez typowe struktury, takie jak tablice, listy itp., a wykonywanie LINQ zapytań nad kolekcją jest prawie zawsze nieco wolniejsze, chociaż przyjemniej jest pisać! Jak powiedzieli inni plakaty, postaw na wyrazistość, a nie milisekundę dodatkowej wydajności.

Dotychczas nie mówiono, że gdy kompilowana jest pętla foreach, jest ona optymalizowana przez kompilator na podstawie kolekcji, którą jest / align = "left" / Oznacza to, że jeśli nie jesteś pewien, której pętli użyć, powinieneś użyć pętli foreach - wygeneruje ona najlepszą pętlę dla ciebie, gdy zostanie skompilowana. Jest też bardziej czytelny.

Kolejną kluczową zaletą pętli foreach jest to, że jeśli implementacja kolekcji ulegnie zmianie (np. z int array na List<int>), to pętla foreach nie będzie wymagała żadnych zmian w kodzie:

foreach (int i in myCollection)

Powyższe jest takie samo bez względu na to, jakiego typu jest Twoja kolekcja, podczas gdy w twoim for jeśli zmienisz myCollection z array na List:

for (int i = 0; i < myCollection.Length, i++)
 8
Author: Alex York,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-13 22:44:27

To ma te same dwie odpowiedzi co większość pytań "co jest szybsze":

1) Jeśli nie mierzysz, nie wiesz.

2) (Bo... To zależy.

To zależy od tego, jak droga jest metoda " MoveNext ()", w stosunku do tego, jak droga jest metoda" this[int index] " dla typu (lub typów) IEnumerable, nad którym będzie iteracja.

Słowo kluczowe "foreach" jest skrótem dla serii operacji-wywołuje GetEnumerator () raz na IEnumerable, wywołuje MoveNext () raz na iterację wykonuje pewne sprawdzanie typu i tak dalej. Najbardziej prawdopodobnym czynnikiem wpływającym na pomiary wydajności jest koszt MoveNext (), ponieważ jest ona wywoływana O (N) razy. Może jest tani, ale może nie.

Słowo kluczowe " for "wygląda bardziej przewidywalnie, ale wewnątrz większości pętli" for "znajdziesz coś w rodzaju" collection[index]". Wygląda to na prostą operację indeksowania tablicy, ale w rzeczywistości jest to wywołanie metody, którego koszt zależy całkowicie od charakteru kolekcja, którą przeglądasz. Pewnie jest tani, ale może nie.

Jeśli struktura bazowa zbioru jest zasadniczo listą połączoną, MoveNext jest bardzo tani, ale indekser może mieć koszt O(N), co czyni rzeczywisty koszt pętli "for" O (N*N).

 8
Author: NSFW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-16 04:03:59

" czy są jakieś argumenty, których mógłbym użyć, aby przekonać go, że pętla for jest dopuszczalna do użycia?"

Nie, jeśli twój szef zajmuje się mikrozarządzaniem do poziomu mówienia ci, jakich konstrukcji języka programowania użyć, naprawdę nic nie możesz powiedzieć. Przepraszam.

 7
Author: Ken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 15:50:52

To prawdopodobnie zależy od rodzaju zbioru, który wyliczysz i implementacji jego indeksatora. Ogólnie rzecz biorąc, użycie foreach prawdopodobnie będzie lepszym podejściem.

Również, będzie działać z każdym IEnumerable - nie tylko rzeczy z indekserami.

 7
Author: Andrew Kennan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-13 17:50:06

Każda konstrukcja języka ma odpowiedni czas i miejsce do użycia. Istnieje powód, dla którego język C# ma cztery oddzielne instrukcje iteracji - każda z nich służy do określonego celu i ma odpowiednie zastosowanie.

Polecam usiąść z szefem i spróbować racjonalnie wyjaśnić, dlaczego pętla for ma cel. Czasami blok iteracji for lepiej opisuje algorytm niż iterację foreach. Gdy jest to prawdą, właściwe jest użycie oni.

Chciałbym również zwrócić uwagę na twojego szefa-wydajność nie jest i nie powinna być problemem w żaden praktyczny sposób - to bardziej kwestia wyrażenia algorytmu w zwięzły, znaczący, możliwy do utrzymania sposób. Mikro-optymalizacje takie jak ten całkowicie pomijają punkt optymalizacji wydajności, ponieważ wszelkie rzeczywiste korzyści z wydajności będą pochodzić z algorytmicznego przeprojektowania i refaktoryzacji, a nie restrukturyzacji pętli.

Jeśli po racjonalnej dyskusji nadal istnieje pogląd autorytarny, to zależy od Ciebie, jak postępować. Osobiście nie byłbym szczęśliwy pracując w środowisku, w którym racjonalne myślenie jest zniechęcane i rozważałbym przeniesienie się na inne stanowisko u innego pracodawcy. Jednak zdecydowanie polecam dyskusję przed zdenerwowaniem - może po prostu dojść do prostego nieporozumienia.
 6
Author: Reed Copsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 18:11:14

To jest to, co robisz wewnątrz pętli, która wpływa na perfomance ,nie rzeczywista konstrukcja pętli (zakładając, że Twój przypadek jest nietrywialny).

 5
Author: Martin Wickman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 16:13:47

To, czy for jest szybsze niż foreach, naprawdę nie ma znaczenia. Szczerze wątpię, że wybór jednego nad drugim będzie miał znaczący wpływ na Twoje wyniki.

Najlepszym sposobem na optymalizację aplikacji jest profilowanie rzeczywistego kodu. To wskaże metody, które odpowiadają za najwięcej pracy / czasu. Najpierw zoptymalizuj. Jeśli wydajność jest nadal nie do przyjęcia, powtórz procedurę.

Ogólnie polecam trzymać się z dala od mikro optymalizacje, ponieważ rzadko przynoszą znaczące zyski. Jedynym wyjątkiem jest optymalizacja zidentyfikowanych ścieżek kluczowych (tzn. jeśli profilowanie identyfikuje kilka wysoce używanych metod, może mieć sens ich obszerna optymalizacja).

 5
Author: Brian Rasmussen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 16:51:17

Obie będą działać prawie dokładnie w ten sam sposób. Napisz jakiś kod, aby użyć obu, a następnie pokaż mu IL. Powinien pokazywać porównywalne obliczenia, co oznacza brak różnicy w wydajności.

 4
Author: cjk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 15:08:28

For ma prostszą logikę do zaimplementowania, więc jest szybsza niż foreach.

 3
Author: Tarik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-13 19:59:32

O ile nie jesteś w konkretnym procesie optymalizacji prędkości, powiedziałbym użyć dowolnej metody, która tworzy najłatwiejszy do odczytania i utrzymania kod.

Jeśli iterator jest już skonfigurowany, jak w przypadku jednej z klas collection, to foreach jest dobrą, łatwą opcją. A jeśli jest to zakres liczb całkowitych, który iteracjonizujesz, to for jest prawdopodobnie czystsze.

 3
Author: GeekyMonkey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-23 09:02:19

Jeffrey Richter mówił o różnicy wydajności między for I foreach w ostatnim podcaście: http://pixel8.infragistics.com/shows/everything.aspx#Episode:9317

 3
Author: Chuck Conway,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-23 10:16:38

W większości przypadków nie ma żadnej różnicy.

Zazwyczaj zawsze musisz używać foreach, gdy nie masz jawnego indeksu liczbowego, i zawsze musisz używać for, gdy nie masz zbioru iterowalnego (np. iteracja na dwuwymiarowej siatce tablicy w górnym trójkącie). Są przypadki, w których masz wybór.

Można by argumentować, że dla pętli może być nieco trudniejsze do utrzymania, jeśli magiczne liczby zaczną pojawiać się w kodzie. Powinieneś należy być zirytowanym, że nie można użyć pętli for i trzeba zbudować kolekcję lub użyć lambda, aby zbudować podkolekcję tylko dlatego, że pętle for zostały zakazane.

 3
Author: Cade Roux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 15:28:42

Wydaje się trochę dziwne, aby całkowicie zabronić używania czegoś takiego jak pętla for.

Jest ciekawy artykuł tutaj , który opisuje wiele różnic w wydajności między obiema pętlami.

Powiedziałbym, że osobiście uważam, że foreach jest bardziej czytelny niż pętle for, ale powinieneś używać najlepszych do danego zadania i nie musisz pisać zbyt długiego kodu, aby zawierać pętlę for, jeśli pętla for jest bardziej odpowiednia.

 3
Author: colethecoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-29 14:41:09

Znalazłem foreach pętlę, która przechodzi przez List faster . Zobacz moje wyniki testu poniżej. W poniższym kodzie iteruję array wielkości 100, 10000 i 100000 oddzielnie za pomocą pętli for i foreach do pomiaru czasu.

Tutaj wpisz opis obrazka

private static void MeasureTime()
    {
        var array = new int[10000];
        var list = array.ToList();
        Console.WriteLine("Array size: {0}", array.Length);

        Console.WriteLine("Array For loop ......");
        var stopWatch = Stopwatch.StartNew();
        for (int i = 0; i < array.Length; i++)
        {
            Thread.Sleep(1);
        }
        stopWatch.Stop();
        Console.WriteLine("Time take to run the for loop is {0} millisecond", stopWatch.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("Array Foreach loop ......");
        var stopWatch1 = Stopwatch.StartNew();
        foreach (var item in array)
        {
            Thread.Sleep(1);
        }
        stopWatch1.Stop();
        Console.WriteLine("Time take to run the foreach loop is {0} millisecond", stopWatch1.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("List For loop ......");
        var stopWatch2 = Stopwatch.StartNew();
        for (int i = 0; i < list.Count; i++)
        {
            Thread.Sleep(1);
        }
        stopWatch2.Stop();
        Console.WriteLine("Time take to run the for loop is {0} millisecond", stopWatch2.ElapsedMilliseconds);

        Console.WriteLine(" ");
        Console.WriteLine("List Foreach loop ......");
        var stopWatch3 = Stopwatch.StartNew();
        foreach (var item in list)
        {
            Thread.Sleep(1);
        }
        stopWatch3.Stop();
        Console.WriteLine("Time take to run the foreach loop is {0} millisecond", stopWatch3.ElapsedMilliseconds);
    }

Zaktualizowano

Po sugestii @jgauffin użyłem kodu @ johnskeet i stwierdziłem, że pętla for z array jest szybsza niż following,

  • pętla Foreach z tablicą.
  • dla pętli z lista.
  • pętla Foreach z listą.

Zobacz moje wyniki testu i Kod poniżej,

Tutaj wpisz opis obrazka

private static void MeasureNewTime()
    {
        var data = new double[Size];
        var rng = new Random();
        for (int i = 0; i < data.Length; i++)
        {
            data[i] = rng.NextDouble();
        }
        Console.WriteLine("Lenght of array: {0}", data.Length);
        Console.WriteLine("No. of iteration: {0}", Iterations);
        Console.WriteLine(" ");
        double correctSum = data.Sum();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j = 0; j < data.Length; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop with Array: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (var i = 0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in data)
            {
                sum += d;
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop with Array: {0}", sw.ElapsedMilliseconds);
        Console.WriteLine(" ");

        var dataList = data.ToList();
        sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            for (int j = 0; j < dataList.Count; j++)
            {
                sum += data[j];
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("For loop with List: {0}", sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            double sum = 0;
            foreach (double d in dataList)
            {
                sum += d;
            }
            if (Math.Abs(sum - correctSum) > 0.1)
            {
                Console.WriteLine("Summation failed");
                return;
            }
        }
        sw.Stop();
        Console.WriteLine("Foreach loop with List: {0}", sw.ElapsedMilliseconds);
    }
 3
Author: Diganta Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-14 08:16:07

Naprawdę możesz go wkręcić w głowę i iść na IQueryable .foreach zamknięcie zamiast:

myList.ForEach(c => Console.WriteLine(c.ToString());
 3
Author: Tad Donaghe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-11 18:28:03

Nie spodziewałbym się, że ktoś znajdzie "ogromną" różnicę wydajności między tymi dwoma.

Myślę, że odpowiedź zależy od tego, czy zbiór, do którego próbujesz uzyskać dostęp, ma szybszą implementację dostępu indeksującego czy szybszą implementację dostępu IEnumerator. Ponieważ IEnumerator często używa indexera i po prostu posiada kopię aktualnej pozycji indeksu, spodziewałbym się, że dostęp do enumeratora będzie co najmniej tak wolny lub wolniejszy niż bezpośredni dostęp do indeksu, ale nie o wiele.

Oczywiście ta odpowiedź nie uwzględnia żadnych optymalizacji, które kompilator może zaimplementować.

 2
Author: JohannesH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-23 10:29:29

Należy pamiętać, że for-loop i foreach-loop nie zawsze są równoważne. Enumeratorzy listy wyrzucą wyjątek, jeśli Lista się zmieni, ale nie zawsze otrzymasz to Ostrzeżenie za pomocą normalnej pętli for. Możesz nawet uzyskać inny wyjątek, jeśli lista zmieni się w niewłaściwym czasie.

 2
Author: Craig Gidney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-17 16:59:48