อะไรคือความแตกต่างระหว่างIEnumerableและArray?
อะไรคือความแตกต่างระหว่างIListและList?
สิ่งเหล่านี้ดูเหมือนจะมีหน้าที่เหมือนกัน
อะไรคือความแตกต่างระหว่างIEnumerableและArray?
อะไรคือความแตกต่างระหว่างIListและList?
สิ่งเหล่านี้ดูเหมือนจะมีหน้าที่เหมือนกัน
คำตอบ:
IEnumerable มีฟังก์ชัน "ทำซ้ำได้" เพียงเล็กน้อยเท่านั้น คุณสามารถสำรวจลำดับได้ แต่ก็เกี่ยวกับมัน สิ่งนี้มีข้อเสีย - ตัวอย่างเช่นการนับองค์ประกอบโดยใช้ IE ไม่ได้มีประสิทธิภาพมากหรือเพื่อให้ได้องค์ประกอบที่ n - แต่ก็มีข้อดีเช่นกันเช่น IEnumerable อาจเป็นลำดับที่ไม่มีที่สิ้นสุดเช่นลำดับของไพรม์
Array คือคอลเล็กชันขนาดคงที่พร้อมการเข้าถึงแบบสุ่ม (เช่นคุณสามารถจัดทำดัชนีได้)
List คือคอลเล็กชันขนาดตัวแปร (เช่นคุณสามารถเพิ่มและลบองค์ประกอบ) ด้วยการเข้าถึงแบบสุ่ม
IList เป็นอินเทอร์เฟซที่แสดงรายการฟังก์ชันการทำงาน (นับเพิ่มลบการเข้าถึงดัชนี) ออกจากคลาสคอนกรีตต่างๆเช่น List, BindingList, ObservableCollection เป็นต้น
IEnumerable เป็นอินเทอร์เฟซที่อนุญาตให้ทำการวนซ้ำผ่านคอลเลกชันของรายการต่างๆ
อาร์เรย์คือ. NET ที่อยู่ภายใน ถือสิ่งของประเภทเดียวกัน แต่มีขนาดคงที่ เมื่อคุณสร้างอาร์เรย์ด้วยองค์ประกอบ x แล้วจะไม่สามารถขยายหรือลดขนาดได้
IList กำหนดอินเทอร์เฟซสำหรับรายการและยังใช้ IEnumerable
รายการใช้อินเทอร์เฟซ IList; เป็นรายการที่เป็นรูปธรรม
ความแตกต่างระหว่างรายการ. NET และอาร์เรย์คือรายการสามารถเพิ่มองค์ประกอบเข้าไปได้ซึ่งจะมีขนาดใหญ่พอที่จะเก็บรายการที่ต้องการทั้งหมดได้ รายการจะเก็บสิ่งนี้ไว้ภายในอาร์เรย์และเมื่ออาร์เรย์ไม่ใหญ่พอที่จะเก็บองค์ประกอบทั้งหมดได้อีกต่อไปอาร์เรย์ใหม่จะถูกสร้างขึ้นและรายการจะถูกคัดลอก
IList & อาร์เรย์ทั้งสองใช้ IEnumerable นั่นเป็นวิธีการทำงานของอินเทอร์เฟซ - คลาสใช้สัญญาและปฏิบัติในลักษณะที่คล้ายกันและสามารถปฏิบัติในลักษณะเดียวกันได้ (คุณรู้ว่าคลาสนั้นใช้ IEnumerable คุณไม่จำเป็นต้องรู้วิธีการหรือวิธีการ) ฉันขอแนะนำให้คุณอ่านอินเทอร์เฟซและอื่น ๆ
การสร้างคอลเลคชัน IEnumerable นั้นขี้เกียจ ตัวอย่าง:
public IEnumerable<int> GetTwoInts()
{
yield return 1;
yield return 2;
}
public void Something()
{
var twoInts = GetTwoInts();
}
ในเมธอด Something การเรียก GetTwoInts () จะไม่ส่งผลให้เมธอด GetTwoInts ถูกเรียกใช้งานจริงเนื่องจากการแจงนับจะไม่ถูกทำซ้ำ
twoIntsในหรือโทรforeach twoInts.ToList()
IEnumerableเป็นอินเตอร์เฟซที่ใช้งานทั่วไปที่ถูกใช้โดยเรียนเป็นจำนวนมากเช่นArray, ListและStringเพื่อที่จะให้คนย้ำกว่าคอลเลกชัน โดยพื้นฐานแล้วมันเป็นสิ่งที่ขับเคลื่อนforeachคำสั่ง
IListโดยทั่วไปเป็นวิธีที่คุณเปิดเผยตัวแปรประเภทListต่อผู้ใช้ปลายทาง อินเทอร์เฟซนี้อนุญาตให้เข้าถึงโดยสุ่มไปยังคอลเลกชัน
เพื่อเสริมคำตอบอื่น ๆ โปรดทราบว่ามีความแตกต่างด้านประสิทธิภาพระหว่างIList<T>และList<T>เมื่อเรียกใช้คำสั่ง foreach
นั่นเป็นเพราะออบเจ็กต์ตัววนซ้ำที่ส่งคืนโดยList<T>.GetEnumeratorเป็นชนิดค่าในขณะที่สิ่งที่ส่งคืนโดยIList<T>.GetEnumeratorเป็นชนิดการอ้างอิงดังนั้นจึงต้องมีการจัดสรรหน่วยความจำ (ดูตัวแจงนับประเภทค่าของรายการใน c # )
ในความคิดของฉันIList<T>ไม่ใช่อินเทอร์เฟซที่ดีมากอยู่ดี ตัวอย่างเช่นการโทรAddสามารถโยนได้ (ดูเหตุใดอาร์เรย์จึงใช้ IList ) หากคุณจำเป็นต้อง Encapsulation คุณต้องการจะดีกว่าการใช้หรือIEnumerable<T>IReadOnlyList<T>
นอกเหนือจากคำตอบอื่น ๆ แล้วการทำความเข้าใจความแตกต่างระหว่าง Enumerable vs List / Array เมื่อใช้ LINQ อาจส่งผลกระทบต่อประสิทธิภาพอย่างมาก ในระยะสั้น Enumerable สามารถรับรู้ได้ว่าเป็นตัวสร้างแบบสอบถามในขณะที่ List / Array เป็นผลลัพธ์ของแบบสอบถาม
ในบริบทของ LINQ เป็น SQL โดยใช้ EntityFramework เดิมเป็นเพียงการสร้างแบบสอบถาม SQL โดยไม่ดำเนินการกับฐานข้อมูลหรือโหลดข้อมูลใด ๆ ลงในหน่วยความจำในขณะที่ข้อมูลในภายหลังนั้นตรงกันข้าม นั่นเป็นเหตุผลที่เราจะเลื่อนการโทรออก.ToList()ไปจนกว่าเราจะต้องการมันในหน่วยความจำเพื่อใช้ตรรกะทางธุรกิจ
ในบริบทอื่นนิพจน์ LINQ ที่ส่งคืน IEnumerable จะเลื่อนการดำเนินการออกไปจนกว่า.ToList()จะถูกเรียก พิจารณาตัวอย่างด้านล่าง:
void Main()
{
var w1 = "AB".AsEnumerable();
Console.WriteLine($"W1: 1");
w1 = w1.Where(W1);
Console.WriteLine($"W1: 2");
w1 = w1.Where(W2);
Console.WriteLine($"W1: 3");
w1.ToList();
Console.WriteLine($"----------");
var w2 = "CD".AsEnumerable();
Console.WriteLine($"W2: 1");
w2 = w2.Where(W1);
Console.WriteLine($"W2: 2");
w2 = w2.ToList();
Console.WriteLine($"W2: 3");
w2 = w2.Where(W2);
Console.WriteLine($"W2: 4");
w2.ToList();
Console.WriteLine($"----------");
}
bool W1(char arg)
{
Console.WriteLine($"W1:{arg}");
return true;
}
bool W2(char arg)
{
Console.WriteLine($"W2:{arg}");
return true;
}
OUTPUT:
W1: 1
W1: 2
W1: 3
W1:A
W2:A
W1:B
W2:B
----------
W2: 1
W2: 2
W1:C
W1:D
W2: 3
W2: 4
W2:C
W2:D
----------
ในตัวอย่างแรกสองรายการ.Where()กำลัง "ต่อท้าย" และดำเนินการพร้อมกันในตอนท้ายเมื่อ.ToList()ถูกเรียกด้วยรายการ " A " ผ่านไปป์ก่อนจากนั้นรายการ " B " จึงเห็น " AABB " ในเอาต์พุตขณะที่ในตัวอย่างที่สอง.Where()จะดำเนินการทุกครั้งถ้าเราเรียก.ToList()ทันทีหลังจากนั้นจึงได้เห็น " ซีดี " และ " ซีดี " อีกครั้งเป็นครั้งที่สองเอาท์พุท ดังนั้นทุกครั้งที่ Enumerable ถูกแปลงเป็น List หรือ Array จะเสียค่าใช้จ่ายO (n)ซ้ำหนึ่งครั้งสำหรับไอเท็มทั้งหมดในคอลเล็กชันซึ่งจะมีผลกระทบต่อประสิทธิภาพเมื่อคอลเลกชันมีขนาดใหญ่
ถึงแม้ว่าเราจะไม่ได้มีแนวโน้มที่จะเขียนโค้ดด้วยวิธีนี้เรียก.ToList()ในระหว่างสาย LINQ แต่มันจะเกิดขึ้นบ่อยครั้งมากขึ้นเมื่อเราเข้าไปในรหัสปัจจัยวิธีนำมาใช้ใหม่ที่ส่งกลับมากกว่าList/ArrayIEnumerable
อย่างไรก็ตามนี่ไม่ได้หมายความว่าเราควรเปิดใช้งานเสมอIEnumerableไป ตามที่กล่าวไว้โดยTowlsonการดำเนินการเช่น.Count()จะทำให้เกิดการวนซ้ำบนคอลเลกชันในขณะที่รายการหรืออาร์เรย์จะมีข้อมูลนี้คำนวณไว้ล่วงหน้าดังนั้นการแปลงเป็นList/Arrayจะมีประสิทธิภาพมากขึ้นหากคุณวางแผนที่จะโทร.Count()หลายครั้ง นี่คือเหตุผลที่มี.Countคุณสมบัติในรายการแทนที่จะเป็น.Count()วิธีการนับ
นี่เป็นกระทู้เก่า แต่ยังคิดว่าจะตอบกลับ IEnumerable เป็นลักษณะการทำงานในขณะที่ Array เป็นโครงสร้างข้อมูล (การรวบรวมองค์ประกอบที่ต่อเนื่องกันที่มีขนาดคงที่ช่วยให้เข้าถึงองค์ประกอบโดยดัชนี) เมื่อ Array ใช้ IEnumerable มันควรจะแสดงคุณสมบัติที่มีอยู่โดยธรรมชาติของ IE ด้วย (เพื่ออำนวยความสะดวกในการทำซ้ำในคอลเลกชัน)