[C#] .NET에서 ‘for’또는 ‘foreach’중 어느 루프가 더 빨리 실행됩니까?

루프가 더 빨리 실행되는 C # / VB.NET / .NET에서 for 또는 foreach?

for루프보다 루프가 더 빨리 작동 한다는 것을 읽은 이후 foreach오래 전에 모든 컬렉션, 일반 컬렉션, 모든 배열 등에 적용되는 것으로 가정했습니다.

Google을 sc이 뒤져서 몇 개의 기사를 찾았지만 대부분 결론을 내리지 못하고 (기사에 대한 의견을 읽음) 공개되지 않았습니다.

이상적인 것은 각 시나리오를 나열하고 최상의 솔루션을 제시하는 것입니다.

예를 들어 (어떻게 해야하는지에 대한 예) :

  1. 1000 개 이상의 문자열 배열을 반복하는 for경우foreach
  2. IList(일반적이지 않은) 문자열 을 반복하는 foreach것보다 낫습니다.for

웹에서 몇 가지 참고 자료를 찾았습니다.

  1. Emmanuel Schanzer의 원본 그랜드 낡은 기사
  2. CodeProject FOREACH 대. 에 대한
  3. 블로그- foreach하지 말아야 할 foreach질문입니다
  4. ASP.NET 포럼-NET 1.1 C # forvsforeach

[편집하다]

가독성 측면 외에도 사실과 수치에 관심이 있습니다. 마지막 마일 성능 최적화가 중요한 응용 프로그램이 있습니다.



답변

Patrick Smacchia 지난 달에 다음과 같은 결론을 내렸다.

  • List의 for 루프는 List의 foreach 루프보다 2 배 이상 저렴합니다.
  • 배열의 루핑은 목록의 루핑보다 약 2 배 저렴합니다.
  • 결과적으로 for를 사용하여 배열을 반복하는 것은 foreach를 사용하여 List를 반복하는 것보다 5 배 저렴합니다 (내 생각에 우리 모두가하는 일입니다).

답변

먼저, 반소 Dmitry의 (현재 삭제 된) 답변에 . 배열의 경우 C # 컴파일러 foreach는 동등한 for루프 와 거의 동일한 코드를 생성 합니다. 이 벤치 마크의 결과가 기본적으로 동일한 이유를 설명합니다.

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

결과 :

For loop: 16638
Foreach loop: 16529

다음으로 컬렉션 유형에 대한 Greg의 요점에 대한 유효성 검사- List<double>위 의 배열을 a 로 변경 하면 근본적으로 다른 결과를 얻습니다. 일반적으로 속도가 상당히 느릴뿐만 아니라 foreach로 액세스하는 것보다 foreach가 상당히 느려집니다. 그럼에도 불구하고, 나는 항상 코드를 단순하게 만드는 for 루프보다 foreach를 선호합니다. 가독성은 거의 항상 중요하기 때문에 마이크로 최적화는 거의 없습니다.


답변

foreach루프는보다 더 구체적 의도를 보여 for루프를 .

사용하여 foreach루프를 코드를 사용하는 모든 사람에게 컬렉션의 위치에 관계없이 컬렉션의 각 멤버에게 무언가를 수행 할 계획임을 알 수 있습니다. 또한 원본 컬렉션을 수정하지 않고 있음을 나타내며 시도하면 예외가 발생합니다.

의 또 다른 장점은 foreach그것이 어떤에서 작동한다는 것입니다 IEnumerable, 어디에 for에만 의미가 있습니다IList 각 요소가 실제로 인덱스를 보유하고 있습니다.

그러나 요소의 색인을 사용해야하는 경우에는 물론 for루프 를 사용해야합니다 . 그러나 색인을 사용할 필요가 없다면 색인을 작성하면 코드가 복잡해집니다.

내가 아는 한 성능에 큰 영향은 없습니다. 미래의 어떤 단계에서는 foreach여러 코어에서 실행 하기 위해 코드를 사용 하는 것이 더 쉬울 수 있지만 지금은 걱정할 것이 없습니다.


답변

성능에 대한 논쟁이있을 때마다, 당신은 당신의 사례를 지원하기 위해 양적 결과를 사용할 수 있도록 작은 테스트를 작성하면됩니다.

StopWatch 클래스를 사용하고 정확성을 위해 수백만 번 반복하십시오. (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

손가락은이 쇼의 결과를 넘어서 그 차이는 무시할 만하다는 것을 보여 주며 가장 유지 보수가 쉬운 코드로 결과를 얻을 수 있습니다.


답변

항상 가깝습니다. 배열의 경우 때로는 for 약간 빠르지 만 foreach표현력이 뛰어나고 LINQ 등을 제공합니다. 일반적으로으로 고정하십시오 foreach.

또한 foreach일부 시나리오에서 최적화 될 수 있습니다. 예를 들어, 링크 된 목록은 인덱서에 의해 끔찍할 수 있지만으로 빠를 수 있습니다 foreach. 실제로이 표준 LinkedList<T>은 이러한 이유로 인덱서를 제공하지도 않습니다.


답변

내 생각에 99 %의 경우에는 그다지 중요하지 않을 것입니다. 왜 가장 이해하기 쉬운 것보다 가장 빠른 것 대신 더 빠른 것을 선택하겠습니까?


답변

둘 사이에 큰 성능 차이는 없을 것입니다. 항상 그렇듯이 “더 빠를까?” 질문, 당신은 항상 “나는 이것을 측정 할 수 있습니다”라고 생각해야합니다.

루프 본문에서 동일한 작업을 수행하는 두 개의 루프를 작성하고 둘 다 실행하고 시간을 정한 다음 속도의 차이가 무엇인지 확인하십시오. 거의 빈 바디와 실제로 수행 할 작업과 유사한 루프 바디로이 작업을 수행하십시오. 컬렉션 유형에 따라 성능 특성이 다를 수 있으므로 사용중인 컬렉션 유형으로 시도하십시오.