จะวนซ้ำคอลเลกชันที่รองรับ IEnumerable ได้อย่างไร?


คำตอบ:


158

ปกติสำหรับแต่ละคนจะทำ:

foreach (var item in collection)
{
    // do your stuff   
}

ซึ่งเร็วกว่า. ElementAt () น่าเสียดายที่การโหวตของฉันถูกล็อคไว้กับคำตอบของ Alexa ดังนั้นฉันจึงไม่สามารถยกเลิกได้ แต่นี่เป็นคำตอบที่ดีที่สุด +1
Leo Gurdian

แล้วคุณจะแก้ไข "Possible multiple enumeration of IEnumerable" ได้อย่างไร?
SharpC

1
@SharpC: วิธีที่ง่ายที่สุดคือดึงผลลัพธ์ออกมาเป็น List <T> หรืออาร์เรย์จากนั้นส่งต่อไปยังที่ต่างๆที่ต้องการทำซ้ำ สิ่งนี้รับประกันได้ว่าการแจงนับผลลัพธ์ (อาจมีราคาแพง) เกิดขึ้นเพียงครั้งเดียว แต่ต้องเสียค่าใช้จ่ายในการจัดเก็บผลลัพธ์ในหน่วยความจำ ขั้นตอนแรกของฉันคือการค้นหาว่าการแจงนับหลายตัวเป็นปัญหาจริงหรือไม่
Fredrik Mörk

94

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

IEnumerable<T> mySequence;
using (var sequenceEnum = mySequence.GetEnumerator())
{
    while (sequenceEnum.MoveNext())
    {
        // Do something with sequenceEnum.Current.
    }
}

ตัวอย่างที่สำคัญคือเมื่อคุณต้องการวนซ้ำสองลำดับพร้อมกันซึ่งไม่สามารถทำได้ด้วยการforeachวนซ้ำ


7
อย่าลืมทิ้งเครื่องแจงนับ
Eric Lippert

@ เอริก: ใช่ฉันจะเพิ่มเข้าไปเพราะมันง่ายที่จะพลาด
Noldorin

1
ฉันคิดว่าจะใช้ได้กับอ็อบเจ็กต์ <T> ของ IEnumerable เท่านั้นไม่ใช่สำหรับ IEnumerable ฉันมีกรณีทั่วไปที่ฉันต้องส่งไปยัง IEnumerable ดังนั้นฉันจึงไม่มีเมธอด GetEnumerator ดีสำหรับกรณีส่วนใหญ่อยู่แล้ว
Fabio Milheiro

51

หรือแม้กระทั่งวิธีการแบบเก่าที่คลาสสิกมาก

IEnumerable<string> collection = new List<string>() { "a", "b", "c" };

for(int i = 0; i < collection.Count(); i++) 
{
    string str1 = collection.ElementAt(i);
    // do your stuff   
}

บางทีคุณอาจต้องการวิธีนี้ด้วย :-)


9
เหตุใดจึงมีการโหวตเพิ่มจำนวนมาก สิ่งนี้จะแจกแจงจำนวน 2n ครั้งแทนที่จะเป็นครั้งเดียว
Roman Reiner

1
@RomanReiner เพราะงานนี้บางคนไม่รำคาญเรื่องการแสดง :)
Khateeb321

@RomanReiner นี่เป็นตัวอย่างที่ดีฉันต้องกำหนดแต่ละองค์ประกอบของคอลเลกชั่นหนึ่งให้กับคอลเลกชันอื่นฉันคิดว่าฉันไม่สามารถทำได้โดยใช้ foreach
AminM

1
หากคุณดูการใช้งาน ElementAt คุณจะพบว่าหากคอลเล็กชันเป็น IList พวกเขาจะส่งคืนองค์ประกอบที่ดัชนีโดยใช้ []; ประสิทธิภาพเช่นเดียวกับ [] อย่างไรก็ตาม; ถ้าไม่พวกเขาจะได้รับ Enumerator และเริ่มการวนซ้ำตามลำดับเพื่อค้นหาองค์ประกอบก่อนที่จะส่งคืนดังนั้นโดยทั่วไปสำหรับแต่ละองค์ประกอบพวกเขาจะสร้างตัวนับใหม่และไปที่รายการอีกครั้ง ...
Israel Garcia

1
ที่แย่กว่านั้นคือ IEnumerable ไม่รองรับ Count () หรือ ElementAt () ฉันคิดว่าเขากำลังคิดถึง IList นี่ไม่ได้ตอบคำถามเลยจริงๆ
krowe


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