ใน. NET วงใดทำงานเร็วกว่า 'for' หรือ 'foreach'


345

ใน C # / VB.NET / .NET ซึ่งห่วงทำงานได้เร็วขึ้นforหรือforeach?

นับตั้งแต่ฉันอ่านว่าforลูปทำงานได้เร็วกว่าforeachลูปเมื่อนานมาแล้วฉันถือว่ามันเป็นจริงสำหรับคอลเลกชันทั้งหมดคอลเลกชันทั่วไปอาร์เรย์ทั้งหมด ฯลฯ

ฉันเฆี่ยนตี Google และพบบทความไม่กี่บทความ แต่ส่วนใหญ่ยังสรุปไม่ได้ (อ่านความคิดเห็นเกี่ยวกับบทความ) และสิ้นสุดวันที่เปิด

สิ่งที่จะเหมาะคือการแสดงรายการแต่ละสถานการณ์และทางออกที่ดีที่สุดสำหรับเรื่องเดียวกัน

ตัวอย่างเช่น (เป็นเพียงตัวอย่างว่าควรจะเป็นอย่างไร):

  1. สำหรับการวนซ้ำสตริงที่forมีมากกว่า1,000 รายการจะดีกว่าforeach
  2. สำหรับการวนซ้ำIListสตริง (ไม่ใช่ทั่วไป) - foreachดีกว่าfor

พบการอ้างอิงบางอย่างบนเว็บสำหรับสิ่งเดียวกัน:

  1. ต้นฉบับบทความเก่าแก่ที่ยิ่งใหญ่โดย Emmanuel Schanzer
  2. CodeProject เทียบกับ FOREACH สำหรับ
  3. บล็อก - เพื่อforeachหรือไม่foreachนั่นคือคำถาม
  4. ฟอรัม ASP.NET - NET 1.1 C # forกับforeach

[แก้ไข]

นอกจากความสามารถในการอ่านของมันฉันยังสนใจในข้อเท็จจริงและตัวเลข มีแอพพลิเคชั่นที่การบีบอัดประสิทธิภาพการทำงานให้มีประสิทธิภาพ


3
ความแตกต่างยังคงมีอยู่ โดยเฉพาะอย่างยิ่งอาร์เรย์ควรเร็วพอ ๆ กับ foreach แต่สำหรับทุกสิ่งทุกอย่าง loops ธรรมดาจะเร็วกว่า แน่นอนว่าส่วนใหญ่แล้วสิ่งนี้จะไม่สร้างความแตกต่างและแน่นอนว่าผู้เรียบเรียง JIT ที่ชาญฉลาดในทางทฤษฎีสามารถกำจัดความแตกต่างได้
jalf

3
หากไม่มีบริบทฉันไม่รู้ว่าคุณกำลังทำอะไร แต่จะเกิดอะไรขึ้นเมื่อคุณเจออาเรย์ที่เต็มไปบางส่วน
คริส Cudmore

6
โดยวิธีการที่ 2 ล้านครั้ง / เดือนไม่มีอะไรน่ากลัว โดยเฉลี่ยน้อยกว่าการเข้าชมต่อวินาที
Mehrdad Afshari

37
หมายเหตุสำคัญ : คำถามนี้ถูกรวมเข้าด้วยกันเมื่อวานนี้กับคำถามที่ไม่เกี่ยวข้องทั้งหมดเกี่ยวกับการถูกบังคับให้ใช้foreachแทนที่จะเป็นforC # หากคุณเห็นคำตอบที่นี่ซึ่งไม่สมเหตุสมผลเลยนั่นคือเหตุผล ตำหนิผู้ดูแลไม่ใช่คำตอบที่โชคร้าย
TED

7
@TED ​​โอ้ฉันสงสัยว่าที่ "เจ้านายของคุณเป็นคนงี่เง่า" ที่มาจากไหนขอบคุณ
Gaspa79

คำตอบ:


350

Patrick Smacchia บล็อกเมื่อประมาณเดือนที่แล้วโดยมีข้อสรุปดังต่อไปนี้:

  • สำหรับลูปในรายการจะมีราคาถูกกว่า 2 เท่าของลูปในรายการ
  • การวนรอบบนอาร์เรย์นั้นถูกกว่าการวนซ้ำในรายการประมาณ 2 เท่า
  • ผลที่ตามมาคือการวนลูปบนอาเรย์ที่ใช้สำหรับถูกกว่าการวนลูปใน List โดยใช้ foreach 5 เท่า (ซึ่งฉันเชื่อว่าเป็นสิ่งที่เราทุกคนทำ)

130
อย่างไรก็ตามอย่าลืม: "การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากฐานของความชั่วร้ายทั้งหมด"
Oorang

18
@Hardwareguy: เมื่อคุณรู้ว่ามันเกือบจะเร็วขึ้นจนมองไม่เห็นทำไมคุณไม่ควรเริ่มใช้มันโดยทั่วไป? ใช้เวลาไม่นาน
DevinB

47
@devinb การใช้ "for" นั้นยากกว่าการใช้ "foreach" เพราะมันจะเพิ่มโค้ดตัวแปรอื่นเงื่อนไขที่คุณต้องตรวจสอบ ฯลฯ คุณเคยเห็นข้อผิดพลาดแบบออฟไลน์ในลูป "foreach" กี่ครั้ง ?
tster

35
@ ฮาร์ดแวร์แวร์ขอให้ฉันดูว่าฉันได้ตรงนี้ มันใช้เวลานานกว่า 5 เท่าในการวนซ้ำในรายการที่มีforeachมากกว่าการวนซ้ำอาร์เรย์ด้วยforและคุณจะเรียกมันว่าไม่มีนัยสำคัญใช่หรือไม่ ความแตกต่างด้านประสิทธิภาพนั้นอาจมีความสำคัญสำหรับแอปพลิเคชันของคุณและอาจไม่ได้ แต่ฉันจะไม่ยกมือออกจากมือ
โรเบิร์ตฮาร์วีย์

44
การอ่านผ่านโพสต์บล็อกดูเหมือนว่าการทดสอบนั้นดำเนินการใน Debug และไม่ปล่อยเพื่อที่อาจมีปัจจัย นอกจากนี้ความแตกต่างนั้นมีเฉพาะสำหรับค่าใช้จ่ายวนรอบเท่านั้น ไม่ส่งผลกระทบต่อเวลาในการเรียกใช้เนื้อความของลูปเลยซึ่งส่วนใหญ่จะยาวกว่าเวลาที่ใช้ในการย้ายไปยังองค์ประกอบถัดไปของรายการ มันเป็นข้อมูลที่ดีจะรู้ว่าเมื่อคุณได้ระบุอย่างชัดเจนว่ามีปัญหาและคุณได้วัดความแตกต่างในแอปของคุณโดยเฉพาะและมีการปรับปรุงที่เห็นได้ชัด แต่ไม่แน่นอนคำแนะนำทั่วไปที่จะลบทั้งหมดforeachs
Davy8

164

ครั้งแรกที่เคาน์เตอร์เรียกร้องให้มิทรีของ (ลบตอนนี้) คำตอบ สำหรับอาร์เรย์คอมไพเลอร์ 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 เกี่ยวกับประเภทของคอลเล็กชั่นสำคัญ - เปลี่ยนอาร์เรย์เป็น a List<double>ด้านบนและคุณจะได้ผลลัพธ์ที่แตกต่างอย่างสิ้นเชิง ไม่เพียง แต่จะช้าลงอย่างมีนัยสำคัญโดยทั่วไป แต่ foreach จะช้ากว่าการเข้าถึงโดยดัชนีอย่างมีนัยสำคัญ ต้องบอกว่าฉันยังคงเกือบตลอดเวลาที่ต้องการ foreach ไปสำหรับวงที่มันทำให้รหัสง่าย - เพราะการอ่านเป็นเกือบตลอดเวลาที่สำคัญในขณะที่ไมโครเพิ่มประสิทธิภาพไม่ค่อยเป็น


"เปลี่ยนอาร์เรย์ในรายการ <คู่> ในข้างต้นและคุณได้รับผลลัพธ์ที่แตกต่างอย่างสิ้นเชิง" ที่น่าสนใจมากผมไม่ได้คิดเกี่ยวกับเรื่องนั้น
johnc

5
ด้วยความแตกต่างที่แปลกประหลาดในผลลัพธ์ระหว่างการทดสอบของฉันและการวัดเปรียบเทียบของคนอื่นฉันคิดว่านี่จะเป็นบุญในการโพสต์บล็อก ...
Jon Skeet

1
คุณมักจะชอบระหว่างอาร์เรย์และList<T>? ความสามารถในการอ่านที่ดีกว่า trump micro-optimization ในกรณีนั้นด้วยหรือไม่
JohnB

12
@ JohnB: ใช่ - ฉันมักชอบList<T>อาร์เรย์มากกว่า ข้อยกเว้นเป็นchar[]และbyte[]ที่มักจะถือว่าเป็น "ชิ้นข้อมูล" มากกว่าคอลเลกชันปกติ
Jon Skeet

น่าทึ่งฉันได้รับความแตกต่างที่ก้าวร้าวมากขึ้นในเครื่องของฉันเกือบ 10% เพื่อสนับสนุนการใช้งานอาร์เรย์อย่างง่าย ฉันคาดเดาอย่างดุเดือดว่าสิ่งทั้งหมดนี้เกิดจากความกระวนกระวายใจโดยไม่ต้องกังวลเกี่ยวกับตัวแปรพิเศษการตรวจสอบที่ถูกผูกไว้และอื่น ๆ จะน่าสนใจมากถ้ามีคนอธิบายอย่างลึกซึ้งเกี่ยวกับเรื่องนี้
Tamir Daniely

162

foreachลูปแสดงให้เห็นถึงความตั้งใจที่เฉพาะเจาะจงมากขึ้นกว่าforลูป

การใช้การforeachวนซ้ำแสดงให้ทุกคนที่ใช้รหัสของคุณทราบว่าคุณวางแผนที่จะทำอะไรบางอย่างกับสมาชิกแต่ละคนของคอลเล็กชันโดยไม่คำนึงถึงสถานที่ในคอลเลกชัน นอกจากนี้ยังแสดงว่าคุณไม่ได้แก้ไขคอลเลกชันดั้งเดิม (และส่งข้อยกเว้นหากคุณพยายาม)

ข้อดีอีกอย่างของforeachมันก็คือมันทำงานได้ทุกIEnumerableที่ที่เหมาะสมforเท่านั้นIListที่แต่ละองค์ประกอบมีดัชนี

อย่างไรก็ตามหากคุณต้องการใช้ดัชนีขององค์ประกอบแน่นอนว่าคุณควรได้รับอนุญาตให้ใช้การforวนซ้ำ แต่ถ้าคุณไม่ต้องการใช้ดัชนีการมีดัชนีก็แค่ทำให้โค้ดของคุณยุ่งเหยิง

ไม่มีนัยสำคัญด้านประสิทธิภาพการทำงานเท่าที่ฉันทราบ ในบางขั้นตอนในอนาคตมันอาจง่ายกว่าที่จะปรับใช้รหัสforeachเพื่อใช้กับหลายคอร์ แต่นั่นไม่ใช่เรื่องที่น่ากังวลในตอนนี้


23
ctford: ไม่มันไม่ใช่ foreachคอมไพเลอร์สามารถอย่างแน่นอนองค์ประกอบไม่ได้สั่งซื้อใหม่ใน foreachไม่ได้เกี่ยวข้องกับการเขียนโปรแกรมฟังก์ชั่นเลย มันทั้งหมดกระบวนทัศน์ความจำเป็นของการเขียนโปรแกรม You are ผิดพลาดเจตนารมณ์สิ่งที่เกิดขึ้นใน TPL และ PLINQ foreachไป
Mehrdad Afshari

13
@BlueTrin: รับประกันการสั่งซื้อแน่นอน (C # spec มาตรา 8.8.4 กำหนดอย่างเป็นทางการforeachว่าเทียบเท่ากับwhileลูป) ฉันคิดว่าฉันรู้ว่า @ctford หมายถึง งานห้องสมุดขนานช่วยให้คอลเลกชันพื้นฐานเพื่อให้องค์ประกอบในการสั่งซื้อโดยพลการ (โดยการโทร.AsParallelบนนับ) foreachไม่ได้ทำอะไรที่นี่และร่างกายของวงที่จะดำเนินการในหัวข้อเดียว สิ่งเดียวที่ขนานกันคือการสร้างลำดับ
Mehrdad Afshari

6
Enumerable.Select มีโอเวอร์โหลดที่ให้คุณรับดัชนีของรายการดังนั้นแม้ความต้องการดัชนีไม่ได้บังคับใช้ ดูmsdn.microsoft.com/en-us/library/bb534869.aspx
TrueWill

5
ForEach มีประโยชน์สำหรับการอ่านและบันทึกการพิมพ์ ค่าใช้จ่ายสำคัญ แต่; การเปลี่ยน 2 หรือ 3 สำหรับลูปใน UI ผู้ออกแบบเอกสารที่ฉันทำจาก (สำหรับแต่ละ obj ในรายการ) เป็น (สำหรับ i = 0 เป็น list.count-1) ลดเวลาตอบสนองจาก 2-3 วินาทีต่อการแก้ไขเป็นประมาณ 5 วินาทีต่อการแก้ไขในเอกสารขนาดเล็กเพียงแค่วนผ่านวัตถุสองสามร้อย ตอนนี้สำหรับเอกสารที่มีขนาดใหญ่มากไม่มีเวลาเพิ่มมากขึ้นในการวนซ้ำทั้งหมด ฉันไม่รู้ว่ามันเกิดขึ้นได้อย่างไร สิ่งที่ฉันรู้ก็คือทางเลือกคือรูปแบบที่ซับซ้อนในการวนเซตย่อยของวัตถุเท่านั้น ฉันจะเปลี่ยน 5 นาทีทุกวัน! - ไม่ใช่การเพิ่มประสิทธิภาพแบบไมโคร
FastAl

5
@FastAl ความแตกต่างระหว่างforeachและforประสิทธิภาพของรายการปกติคือเศษเสี้ยวของวินาทีสำหรับการวนซ้ำของรายการนับล้านดังนั้นปัญหาของคุณไม่ได้เกี่ยวข้องโดยตรงกับประสิทธิภาพของ foreach อย่างน้อยก็ไม่ใช่วัตถุสักสองสามร้อย ดูเหมือนว่าการใช้ตัวแจงนับที่ใช้งานไม่ได้ในรายการที่คุณใช้อยู่
Mike Marynowski

53

เมื่อใดก็ตามที่มีข้อโต้แย้งเรื่องประสิทธิภาพคุณต้องเขียนข้อสอบเล็ก ๆ เพื่อให้คุณสามารถใช้ผลลัพธ์เชิงปริมาณเพื่อสนับสนุนกรณีของคุณ

ใช้คลาส StopWatch และทำซ้ำสองสามครั้งเพื่อความแม่นยำ (ซึ่งอาจเป็นเรื่องยากหากไม่มีลูป):

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

นิ้วของคุณข้ามผลลัพธ์ของการแสดงนี้ว่าความแตกต่างนั้นเล็กน้อยและคุณก็อาจจะทำอะไรก็ได้ในโค้ดที่รักษาได้มากที่สุด


13
แต่คุณไม่สามารถเปรียบเทียบประสิทธิภาพของ for และ foreach ได้ ควรใช้ในสถานการณ์ต่าง ๆ
Michael Krelin - แฮกเกอร์

7
ฉันเห็นด้วยกับคุณ Michael คุณไม่ควรเลือกอันไหนที่จะใช้ตามประสิทธิภาพ - คุณควรเลือกอันที่เหมาะสมที่สุด! แต่ถ้าเจ้านายของคุณบอกว่า "อย่าใช้เพราะมันช้ากว่าหน้า" นี่เป็นวิธีเดียวที่จะโน้มน้าวเขาได้ว่าความแตกต่างนั้นเล็กน้อย
Rob Fonseca-Ensor

"(สิ่งนี้อาจทำได้ยากโดยไม่มีการวนซ้ำ)" หรือคุณสามารถใช้การวนรอบสักครู่ได้
jonescb

49

มันจะปิดเสมอ สำหรับอาเรย์บางครั้ง forเร็วกว่าเล็กน้อย แต่foreachมีความหมายมากกว่าและมี LINQ ฯลฯ โดยทั่วไปforeachแล้ว

นอกจากนี้foreachอาจปรับให้เหมาะสมในบางสถานการณ์ ยกตัวอย่างเช่นรายการที่เชื่อมโยงอาจจะน่ากลัวโดยดัชนี foreachแต่มันอาจจะเป็นได้อย่างรวดเร็วโดย จริงๆแล้วมาตรฐานLinkedList<T>ไม่ได้เสนอตัวทำดัชนีด้วยเหตุผลนี้


ดังนั้นคุณจะพูดว่าLinkedList<T>ผอมกว่าList<T>? และถ้าฉันมักจะใช้foreach(แทนfor) ฉันดีกว่าใช้LinkedList<T>หรือไม่
JohnB

2
@JohnB - ไม่เอนกาย แตกต่างกันเพียง ตัวอย่างเช่นแต่ละโหนดในรายการที่เชื่อมโยงมีการอ้างอิงเพิ่มเติมที่ไม่จำเป็นสำหรับแบนอาร์เรย์ (ซึ่งยังสนับสนุนList<T>) ก็จะมากขึ้นว่ามันมีราคาถูกเพื่อแทรก / ลบ
Marc Gravell

36

ฉันเดาว่ามันอาจจะไม่สำคัญในกรณี 99% ดังนั้นทำไมคุณถึงเลือกที่เร็วกว่าแทนที่จะเป็นสิ่งที่เหมาะสมที่สุด


6
@klew ถ้าคุณใส่รหัสของคุณจริงๆคุณไม่จำเป็นต้องเดาว่า 20% จะต้องเร็วที่สุดเท่าที่จะเป็นไปได้ คุณอาจจะพบว่าจำนวนลูปจริงที่ต้องรวดเร็วนั้นต่ำกว่ามาก นอกจากนี้คุณกำลังพูดจริง ๆ หรือว่าการวนลูปเป็นที่ที่คุณใช้เวลาของคุณเมื่อเทียบกับสิ่งที่คุณทำจริง ๆ ในวงนั้น
tster

32

ไม่น่าจะมีความแตกต่างด้านประสิทธิภาพอย่างมากระหว่างทั้งสอง เช่นเคยเมื่อต้องเผชิญกับ "ซึ่งเร็วกว่า" คำถามคุณควรคิดว่า "ฉันสามารถวัดสิ่งนี้ได้"

เขียนสองลูปที่ทำสิ่งเดียวกันในร่างกายของลูปรันและกำหนดเวลาทั้งสองและดูว่าอะไรคือความแตกต่างของความเร็ว ทำสิ่งนี้กับทั้งร่างกายที่เกือบจะว่างเปล่าและลำตัวคล้ายกับสิ่งที่คุณกำลังทำอยู่ ลองใช้กับประเภทคอลเลกชันที่คุณใช้อยู่เพราะคอลเลกชันประเภทต่างๆอาจมีคุณสมบัติด้านประสิทธิภาพที่แตกต่างกัน


32

มีเหตุผลที่ดีมากที่จะชอบ foreachลูปมากกว่าforลูป หากคุณสามารถใช้foreachลูปได้หัวหน้าของคุณจะถูกต้อง

อย่างไรก็ตามไม่ใช่ว่าการวนซ้ำทุกครั้งจะผ่านรายการตามลำดับทีละรายการ หากเขาถูกห้ามไม่ให้ทำเช่นนั้นผิด

ถ้าฉันเป็นคุณสิ่งที่ผมจะทำคือการเปิดทั้งหมดของธรรมชาติของคุณสำหรับลูปลงในการเรียกซ้ำ นั่นเป็นการสอนเขาและมันก็เป็นการออกกำลังกายทางจิตที่ดีสำหรับคุณ


การเรียกซ้ำจะเปรียบเทียบกับการforวนซ้ำและการforeachวนรอบที่ชาญฉลาดได้อย่างไร
JohnB

มันขึ้นอยู่กับ. หากคุณใช้การเรียกซ้ำแบบหางและคอมไพเลอร์ของคุณฉลาดพอที่จะสังเกตเห็นว่ามันอาจเหมือนกัน OTOH: ถ้าไม่ทำและคุณทำอะไรโง่ ๆ เช่นส่งข้อมูลที่ไม่ได้เปลี่ยนแปลง (เป็นจำนวนมาก) เป็นพารามิเตอร์หรือประกาศโครงสร้างขนาดใหญ่บนสแต็กเป็นคนในท้องถิ่นมันอาจช้ามากจริงๆ (หรือแม้กระทั่งแรมหมด)
TED

Ahhh ฉันเห็นว่าทำไมคุณถึงถามตอนนี้ คำตอบนี้เป็นคำถามที่แตกต่างอย่างสิ้นเชิง ด้วยเหตุผลบางอย่างที่โจนาธานแซมสันรวมทั้งสองเมื่อวานนี้ เขาไม่ควรทำอย่างนั้นจริงๆ คำตอบที่ถูกผสานจะไม่มีเหตุผลใด ๆ
TED

18

Jeffrey Richter ใน TechEd 2005:

"ฉันได้เรียนรู้มาหลายปีแล้วที่คอมไพเลอร์ C # นั้นเป็นคนโกหกสำหรับฉัน" .. "มันเกี่ยวกับหลายสิ่งหลายอย่าง" .. "เหมือนตอนที่คุณวนลูป foreach ... " .. "... นั่นคือหนึ่งบรรทัดของโค้ดที่คุณเขียน แต่สิ่งที่คอมไพเลอร์ของ C # แยกออกมาเพื่อที่จะทำให้มันเป็นปรากฎการณ์ ลอง / ในที่สุดบล็อกในนั้นภายในบล็อกสุดท้ายมันจะปลดตัวแปรของคุณไปยังอินเทอร์เฟซ IDisposable และถ้านักแสดงได้สำเร็จมันเรียกวิธีการกำจัดมันภายในวงมันเรียกคุณสมบัติปัจจุบันและวิธีการ MoveNext ซ้ำภายในวง วัตถุถูกสร้างขึ้นภายใต้ฝาครอบผู้คนจำนวนมากใช้ foreach เพราะการเข้ารหัสง่ายมากทำได้ง่ายมาก .. ".. " foreach ไม่ค่อยดีในแง่ของประสิทธิภาพ

เว็บคาสต์ตามความต้องการ: http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032292286&EventCategory=3&culture=th-US&CountryCode=US


12

นี่มันไร้สาระ ไม่มีเหตุผลที่น่าสนใจที่จะห้าม for-loop, performance-wise หรืออื่น ๆ

ดูบล็อกของ Jon Skeetสำหรับการวัดประสิทธิภาพและการขัดแย้งอื่น ๆ


2
อัปเดตลิงก์: codeblog.jonskeet.uk/2009/01/29/…
แมตต์

โครงสร้างวนรอบที่เร็วขึ้นอยู่กับสิ่งที่คุณต้องการวนซ้ำ บล็อกอื่นที่ใช้เปรียบเทียบการทำซ้ำหลายครั้งบนวัตถุหลายชนิดเช่น DataRows และวัตถุที่กำหนดเอง นอกจากนี้ยังมีประสิทธิภาพของโครงสร้างลูปในขณะที่ไม่เพียง แต่สร้างและ foreach ลูปการสร้าง
Coder ฟรี 24

11

ในกรณีที่คุณทำงานกับชุดของวัตถุforeachจะดีกว่า แต่ถ้าคุณเพิ่มจำนวนforห่วงจะดีกว่า

โปรดทราบว่าในกรณีสุดท้ายคุณสามารถทำสิ่งต่อไปนี้:

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

forแต่แน่นอนไม่ได้ดำเนินการที่ดีกว่าก็จริงมีประสิทธิภาพการทำงานที่แย่ลงเมื่อเทียบกับ


"ดีกว่า" สามารถถกเถียงได้: มันช้าลงและตัวดีบัก dnspy ​​จะไม่เจาะเข้าไปใน C # foreach (แม้ว่าตัวดีบัก VS2017 จะ) บางครั้งสามารถอ่านได้มากขึ้น แต่ถ้าคุณสนับสนุนภาษาที่ไม่มีมันอาจเป็นเรื่องน่ารำคาญ
Zeek2

10

สิ่งนี้จะช่วยคุณ:

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

ใช้:

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

สำหรับการชนะที่มากขึ้นคุณอาจรับผู้แทนสามคนเป็นพารามิเตอร์


1
ความแตกต่างเล็ก ๆ น้อย ๆ อย่างหนึ่งคือการforวนซ้ำจะเขียนเพื่อแยกจุดสิ้นสุดของช่วง (เช่น0 <= i < 10) Parallel.Forยังทำเช่นนั้นเพื่อให้สามารถเปลี่ยนได้อย่างง่ายดายด้วยforลูปทั่วไป
Groo

9

คุณสามารถอ่านได้ในDeep .NET - ตอนที่ 1 ซ้ำ

มันครอบคลุมผลลัพธ์ (โดยไม่มีการเริ่มต้นครั้งแรก) จากซอร์สโค้ด. NET ไปจนถึงการถอดแยกชิ้นส่วน

ตัวอย่าง - การทำซ้ำอาร์เรย์ด้วยลูป foreach: ป้อนคำอธิบายรูปภาพที่นี่

และ - ทำรายการซ้ำด้วย foreach loop: ป้อนคำอธิบายรูปภาพที่นี่

และผลลัพธ์สุดท้าย: ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่


8

ความแตกต่างของความเร็วใน a for- และ a foreach-loop นั้นเล็กมากเมื่อคุณวนลูปผ่านโครงสร้างทั่วไปเช่นอาร์เรย์รายการ ฯลฯ และการทำLINQแบบสอบถามบนคอลเลกชันนั้นมักจะช้ากว่าเล็กน้อยแม้ว่ามันจะดีกว่าในการเขียน! อย่างที่ผู้โพสต์คนอื่นพูดเอาไว้เพื่อความเป็นเลิศมากกว่าการแสดงเป็นมิลลิวินาที

สิ่งที่ยังไม่ได้กล่าวถึงก็คือเมื่อforeachรวบรวมลูปแล้วจะได้รับการปรับปรุงโดยคอมไพเลอร์ตามการรวบรวมที่วนซ้ำ นั่นหมายความว่าเมื่อคุณไม่แน่ใจว่าจะใช้ลูปใดคุณควรใช้foreachลูป - มันจะสร้างลูปที่ดีที่สุดสำหรับคุณเมื่อคอมไพล์แล้ว มันอ่านได้มากขึ้นเช่นกัน

ข้อได้เปรียบที่สำคัญอีกประการหนึ่งของforeachลูปคือหากการใช้งานคอลเลกชันของคุณเปลี่ยนไป (จากตัวอย่างเป็น int arrayถึงList<int>ตัวอย่าง) foreachลูปของคุณจะไม่ต้องการการเปลี่ยนแปลงโค้ดใด ๆ :

foreach (int i in myCollection)

ด้านบนจะเหมือนกันไม่ว่าประเภทของคอลเลกชันของคุณจะเป็นอย่างไรในขณะที่อยู่ในforลูปของคุณสิ่งต่อไปนี้จะไม่สร้างหากคุณเปลี่ยนmyCollectionจากarraya เป็น a List:

for (int i = 0; i < myCollection.Length, i++)

7

"มีข้อโต้แย้งใด ๆ ที่ฉันสามารถใช้เพื่อช่วยโน้มน้าวเขาว่า for loop นั้นยอมรับได้หรือไม่"

ไม่ถ้าเจ้านายของคุณกำลังอ่านระดับไมโครถึงระดับที่จะบอกคุณว่าภาษาการเขียนโปรแกรมที่สร้างขึ้นเพื่อใช้งานจริง ๆ คุณไม่สามารถพูดอะไรได้ ขอโทษ


7

มันอาจขึ้นอยู่กับประเภทของคอลเลกชันที่คุณระบุและการใช้งานตัวทำดัชนีของมัน โดยทั่วไปแล้วการใช้foreachน่าจะเป็นวิธีที่ดีกว่า

นอกจากนี้มันจะทำงานกับสิ่งใดก็ได้IEnumerable- ไม่ใช่เพียงแค่สิ่งที่ทำดัชนี


7

คำตอบนี้มีสองคำตอบเหมือนกับคำถาม "ซึ่งเร็วกว่า":

1) ถ้าคุณไม่วัดคุณก็ไม่รู้

2) (เพราะ ... ) มันขึ้นอยู่กับ

ขึ้นอยู่กับว่าวิธี "MoveNext ()" นั้นแพงแค่ไหนเมื่อเทียบกับวิธีการ "this [int index]" ที่มีราคาแพงสำหรับประเภท (หรือประเภท) ของ IEnumerable ที่คุณจะวนซ้ำ

คำสำคัญ "foreach" นั้นย่อมาจากชุดของการดำเนินการ - มันเรียก GetEnumerator () หนึ่งครั้งใน IEnumerable มันเรียกว่า MoveNext () หนึ่งครั้งต่อการทำซ้ำมันจะตรวจสอบบางประเภทและอื่น ๆ สิ่งที่น่าจะส่งผลต่อการวัดประสิทธิภาพมากที่สุดคือต้นทุนของ MoveNext () เนื่องจากได้รับการเรียกใช้ O (N) ครั้ง อาจจะถูก แต่อาจจะไม่ใช่

คำหลัก "สำหรับ" ดูเหมือนจะคาดเดาได้มากขึ้น แต่ส่วนใหญ่ "สำหรับ" ลูปคุณจะพบบางสิ่งเช่น "คอลเลกชัน [ดัชนี]" ดูเหมือนว่าการดำเนินการทำดัชนีแบบง่าย ๆ แต่จริง ๆ แล้วเป็นการเรียกใช้เมธอดซึ่งค่าใช้จ่ายขึ้นอยู่กับลักษณะของคอลเลกชันที่คุณวนซ้ำ อาจจะราคาถูก แต่อาจจะไม่ใช่

หากโครงสร้างพื้นฐานของคอลเลกชันนั้นเป็นรายการที่เชื่อมโยงกันแล้ว MoveNext นั้นสกปรกราคาถูก แต่ตัวสร้างดัชนีอาจมีต้นทุน O (N) ทำให้ต้นทุนที่แท้จริงของ "for" loop O (N * N)


6

โครงสร้างภาษาทุกภาษามีเวลาและสถานที่ที่เหมาะสมสำหรับการใช้งาน มีเหตุผลที่ภาษา C # มีคำสั่งการทำซ้ำสี่ข้อความ - แต่ละข้อความมีไว้เพื่อวัตถุประสงค์เฉพาะและมีการใช้งานที่เหมาะสม

ฉันแนะนำให้นั่งกับเจ้านายของคุณและพยายามอธิบายเหตุผลว่าทำไมการforวนซ้ำจึงมีวัตถุประสงค์ มีบางครั้งที่forการบล็อกการวนซ้ำอย่างชัดเจนอธิบายอัลกอริทึมมากกว่าการforeachทำซ้ำ เมื่อสิ่งนี้เป็นจริงมันก็เหมาะสมที่จะใช้มัน

ฉันจะชี้ให้เจ้านายของคุณ - การแสดงไม่ได้และไม่ควรเป็นปัญหาในทางปฏิบัติใด ๆ - มันเป็นเรื่องของการแสดงออกของอัลกอริทึมในลักษณะรวบรัด, มีความหมายและสามารถบำรุงรักษาได้ การปรับให้เหมาะสมขนาดเล็กเช่นนี้ทำให้พลาดจุดเพิ่มประสิทธิภาพอย่างสมบูรณ์เนื่องจากผลประโยชน์ที่แท้จริงจะมาจากการออกแบบอัลกอริทึมและการปรับโครงสร้างใหม่ไม่ใช่การปรับโครงสร้างแบบวนซ้ำ

หากหลังจากการอภิปรายอย่างมีเหตุผลยังคงมีมุมมองแบบเผด็จการนี้ขึ้นอยู่กับคุณว่าจะดำเนินการอย่างไร โดยส่วนตัวแล้วฉันจะไม่มีความสุขในการทำงานในสภาพแวดล้อมที่ความคิดที่เป็นเหตุเป็นผลท้อแท้และจะพิจารณาย้ายไปทำงานในตำแหน่งอื่นภายใต้นายจ้างคนอื่น อย่างไรก็ตามฉันขอแนะนำให้สนทนาก่อนที่จะอารมณ์เสีย - อาจมีความเข้าใจผิด ๆ เกิดขึ้น


5

มันเป็นสิ่งที่คุณทำในลูปที่มีผลต่อความสมบูรณ์ไม่ใช่การสร้างลูปจริง (สมมติว่ากรณีของคุณไม่สำคัญ)


5

ไม่ว่าforจะเร็วกว่าforeachนั้นจริง ๆ นอกเหนือจากจุด ฉันสงสัยอย่างจริงจังว่าการเลือกตัวเลือกอื่นจะส่งผลกระทบอย่างมีนัยสำคัญต่อประสิทธิภาพการทำงานของคุณ

วิธีที่ดีที่สุดในการเพิ่มประสิทธิภาพแอปพลิเคชันของคุณคือการสร้างโปรไฟล์ของรหัสจริง ที่จะระบุวิธีการที่บัญชีสำหรับการทำงานมากที่สุด / เวลา เพิ่มประสิทธิภาพเหล่านั้นก่อน หากประสิทธิภาพยังไม่เป็นที่ยอมรับให้ทำซ้ำขั้นตอน

ตามกฎทั่วไปฉันขอแนะนำให้อยู่ห่างจากการเพิ่มประสิทธิภาพขนาดเล็กเนื่องจากพวกเขาจะไม่ค่อยได้ผลกำไรที่มีนัยสำคัญใด ๆ ข้อยกเว้นเพียงอย่างเดียวคือเมื่อเพิ่มประสิทธิภาพเส้นทางที่ร้อนแรงที่ระบุ (เช่นหากการทำโปรไฟล์ของคุณระบุวิธีการที่ใช้กันอย่างแพร่หลายสักสองสามวิธี


หากการเพิ่มประสิทธิภาพประเภทเดียวที่ฉันต้องทำในโครงการที่ฉันทำงานคือการปรับให้เหมาะสมแบบเล็กที่สุดฉันจะเป็นผู้พักแรมที่มีความสุข น่าเศร้าที่กรณีนี้ไม่เคยเกิดขึ้น
Yannick Motton

2
forเร็วกว่าforeachเล็กน้อย ฉันจะคัดค้านคำสั่งนี้อย่างจริงจัง นั่นขึ้นอยู่กับการรวบรวม หากคลาส list ที่เชื่อมโยงจัดเตรียมตัวทำดัชนีด้วยพารามิเตอร์จำนวนเต็มฉันคาดว่าจะใช้การforวนซ้ำที่เป็น O (n ^ 2) ในขณะที่foreachคาดว่าจะเป็น O (n)
Mehrdad Afshari

@ Merhdad: จริง ๆ แล้วมันเป็นจุดที่ดี ฉันแค่คิดเกี่ยวกับกรณีปกติของการจัดทำดัชนีรายการ (เช่นอาร์เรย์) ฉันจะพูดซ้ำเพื่อสะท้อนให้เห็นว่า ขอบคุณ
Brian Rasmussen

@Mehrdad Afshari: ดัชนีคอลเลกชันโดยจำนวนเต็มอาจจะมากช้ากว่าแจงมากกว่านั้น แต่คุณกำลังเปรียบเทียบการใช้for และการค้นหาตัวทำดัชนีกับการใช้งานforeachด้วยตัวเอง ผมคิดว่าคำตอบ @ Brian Rasmussen เป็นที่ถูกต้องที่นอกเหนือจากการใช้งานใด ๆ กับคอลเลกชันมักจะเร็วกว่าเล็กน้อยfor foreachอย่างไรก็ตามforรวมถึงการค้นหาคอลเลกชันจะช้ากว่าforeachตัวเองเสมอ
Daniel Pryden

@Daniel: อาจเป็นเพราะคุณมีอาร์เรย์ธรรมดาซึ่งทั้งคู่จะสร้างรหัสที่เหมือนกันหรือมีตัวสร้างดัชนีที่เกี่ยวข้องเมื่อคุณใช้forคำสั่ง ธรรมดาforห่วงกับตัวแปรควบคุมจำนวนเต็มไม่เทียบเท่ากับforeachเพื่อให้ออก ฉันเข้าใจความหมายของ @Brian และมันถูกต้องตามที่คุณพูด แต่คำตอบอาจทำให้เข้าใจผิด Re: จุดสุดท้ายของคุณ: ไม่จริงforมากกว่ายังคงเร็วกว่าList<T> foreach
Mehrdad Afshari

4

ทั้งสองจะทำงานในลักษณะเดียวกัน เขียนรหัสเพื่อใช้ทั้งสองอย่างจากนั้นแสดง IL ให้เขาดู มันควรแสดงการคำนวณที่เปรียบเทียบกันได้ซึ่งหมายความว่าไม่มีความแตกต่างในประสิทธิภาพ


คอมไพเลอร์รับรู้ลูป foreach ที่ใช้กับอาร์เรย์ / ILists ฯลฯ และเปลี่ยนเป็นลูป
Callum Rogers

3
แสดงให้เขาเห็นบรรทัดของการพิสูจน์ที่ไม่ฉลาดหลักแหลมว่ามันโอเคและขอการพิสูจน์ของเขาว่ามันไม่เป็นไร
cjk

3

เพราะมีตรรกะที่ง่ายกว่าในการนำไปใช้ดังนั้นจึงเร็วกว่า foreach


3

หากคุณไม่ได้อยู่ในกระบวนการปรับแต่งความเร็วที่เฉพาะเจาะจงฉันจะบอกว่าใช้วิธีใดในการสร้างและอ่านรหัสที่ง่ายที่สุด

หากตัววนซ้ำติดตั้งไว้แล้วเช่นเดียวกับคลาสการรวบรวมชุดหนึ่ง foreach นั้นเป็นตัวเลือกที่ง่าย และถ้ามันเป็นช่วงจำนวนเต็มคุณกำลังวนซ้ำมันอาจจะสะอาดกว่า



3

ในกรณีส่วนใหญ่ไม่มีความแตกต่าง

โดยทั่วไปคุณจะต้องใช้ foreach ทุกครั้งเมื่อคุณไม่มีดัชนีตัวเลขที่ชัดเจนและคุณจะต้องใช้เสมอเมื่อคุณไม่มีคอลเลกชันที่ใช้ซ้ำได้ (เช่นวนซ้ำในตารางอาร์เรย์สองมิติในสามเหลี่ยมด้านบน) . มีบางกรณีที่คุณมีทางเลือก

อาจมีคนแย้งว่าสำหรับลูปอาจเป็นเรื่องยากขึ้นเล็กน้อยในการรักษาหากตัวเลขเวทย์มนตร์เริ่มปรากฏในรหัส คุณควรถูกรำคาญที่ไม่สามารถใช้สำหรับลูปและต้องสร้างคอลเลกชันหรือใช้แลมบ์ดาเพื่อสร้างการรวบรวมย่อยแทนเพียงเพราะลูปถูกแบน


3

ดูเหมือนจะแปลกเล็กน้อยที่ห้ามไม่ให้มีการใช้สิ่งใดสิ่งหนึ่งเช่น for for loop โดยสิ้นเชิง

มีบทความที่น่าสนใจที่นี่ซึ่งครอบคลุมความแตกต่างของประสิทธิภาพระหว่างสองลูป

ฉันจะบอกว่าเป็นการส่วนตัวที่ฉันพบว่า foreach อ่านได้มากกว่าสำหรับ loops อีกเล็กน้อย แต่คุณควรใช้สิ่งที่ดีที่สุดสำหรับงานในมือและไม่ต้องเขียนโค้ดแบบยาวพิเศษเพื่อรวมลูป foreach ถ้า for loop นั้นเหมาะสมกว่า


ใบเสนอราคาที่จำเป็นต้องมีรูปแบบบทความที่คุณลิงก์ไปยัง: "... หากคุณวางแผนที่จะเขียนโค้ดประสิทธิภาพสูงที่ไม่ได้เป็นของสะสมใช้สำหรับลูปแม้แต่สำหรับคอลเลกชัน foreach อาจดูมีประโยชน์เมื่อใช้ แต่ก็ไม่มีประสิทธิภาพ"
NickFitz

3

ผมพบว่าforeachห่วงซึ่ง iterating ผ่านได้เร็วขึ้นList ดูผลการทดสอบของฉันด้านล่าง ในรหัสด้านล่างฉันทำซ้ำarrayขนาด 100, 10,000 และ 100000 แยกต่างหากโดยใช้forและforeachวนรอบเพื่อวัดเวลา

ป้อนคำอธิบายรูปภาพที่นี่

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

ปรับปรุง

หลังจากข้อเสนอแนะ @jgauffin ฉันใช้รหัส @johnskeet และพบว่าการforวนซ้ำด้วยarrayเร็วกว่าการติดตาม

  • Foreach วนกับอาร์เรย์
  • สำหรับวงที่มีรายการ
  • foreach วนกับรายการ

ดูผลการทดสอบและรหัสด้านล่างของฉัน

ป้อนคำอธิบายรูปภาพที่นี่

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
นี่เป็นการทดสอบที่แย่มาก a) คุณทำซ้ำน้อยเกินไปเพื่อให้ได้คำตอบที่สรุปข) Thread.Sleep จะไม่รอหนึ่งมิลลิวินาทีจริงๆ ใช้วิธีการเดียวกับ Jon Skeet ในคำตอบของเขา
jgauffin

1
99.99% ของเวลาถูกใช้อย่างแน่นอนใน thread.sleep (ซึ่งไม่รับประกันว่าจะส่งคืนได้เร็วเพียงใดยกเว้นจะไม่มาก่อนเวลานั้นอย่างน้อย) การวนซ้ำนั้นเร็วมากและการนอนหลับช้ามากคุณไม่ได้ใช้การทดสอบแบบก่อนหน้าในภายหลัง
Ronan Thibaudau

3

คุณสามารถขันหัวของเขาและไปหา IQueryable ก่อนปิดแทน:

myList.ForEach(c => Console.WriteLine(c.ToString());

3
myList.ForEach(Console.WriteLine)ฉันต้องการเปลี่ยนสายของคุณด้วยรหัส
Mehrdad Afshari

2

ฉันไม่คิดว่าจะมีใครพบความแตกต่างของประสิทธิภาพการทำงาน "ใหญ่" ระหว่างสองคนนี้

ฉันเดาว่าคำตอบนั้นขึ้นอยู่กับว่าคอลเลกชันที่คุณพยายามเข้าถึงนั้นมีการใช้การเข้าถึงตัวทำดัชนีที่เร็วขึ้นหรือการใช้การเข้าถึง IEnumerator ที่เร็วขึ้น เนื่องจาก IEnumerator มักใช้ตัวสร้างดัชนีและเก็บสำเนาตำแหน่งดัชนีปัจจุบันฉันจึงคาดว่าการเข้าถึงตัวแจงนับจะอย่างน้อยช้าหรือช้ากว่าการเข้าถึงดัชนีโดยตรง แต่ไม่มากนัก

แน่นอนคำตอบนี้ไม่ได้คำนึงถึงการเพิ่มประสิทธิภาพใด ๆ ที่คอมไพเลอร์อาจนำไปใช้


คอมไพเลอร์ C # ทำการปรับให้เหมาะสมน้อยมากจริง ๆ แล้วปล่อยให้ JITter เกิดขึ้นจริง
ljs

JITter นั้นเป็นคอมไพเลอร์ ... ใช่มั้ย
JohannesH

2

โปรดทราบว่า for-loop และ foreach-loop นั้นไม่เสมอกัน ตัวแจงนับรายชื่อจะโยนข้อยกเว้นหากรายการเปลี่ยนแปลง แต่คุณจะไม่ได้รับคำเตือนนั้นพร้อมกับปกติสำหรับลูป คุณอาจได้รับข้อยกเว้นที่แตกต่างกันหากรายการเปลี่ยนแปลงในเวลาที่ผิด


หากรายการนั้นเปลี่ยนไปจากภายใต้คุณคุณไม่สามารถพึ่งพาตัวแจงนับที่สำรองลูป foreach เพื่อบอกคุณได้ว่า จะไม่ตรวจสอบอีกครั้งหลังจากส่งคืนค่าให้กับคุณแล้วส่งผลให้เกิดการแข่งขัน
hoodaticus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.