อาร์เรย์กับรายการ <T>: เมื่อใดควรใช้


593
MyClass[] array;
List<MyClass> list;

อะไรคือสถานการณ์สมมติเมื่อสถานการณ์หนึ่งดีกว่าอีกสถานการณ์หนึ่ง และทำไม?


9
อาร์เรย์ค่อนข้างล้าสมัยดังที่เห็นในการอภิปรายยอดนิยมที่นี่ นอกจากนี้ยังชี้ให้เห็นที่นี่และโฮสต์ของเราในบล็อก
gimel

9
ถ้าฉันไม่ผิดรายการ <> มีอาร์เรย์เป็นโครงสร้างภายใน เมื่อใดก็ตามที่อาร์เรย์ภายในถูกเติมเต็มเพียงคัดลอกเนื้อหาไปยังอาร์เรย์ที่มีขนาดเป็นสองเท่า (หรือค่าคงที่อื่น ๆ คูณด้วยขนาดปัจจุบัน) en.wikipedia.org/wiki/Dynamic_array
Ykok

Ykok: สิ่งที่คุณพูดเกี่ยวกับสิทธิดูเหมือนผมพบว่ารหัสที่มาของรายการ <> ที่นี่
Carol

19
@gimel การโต้เถียงว่าอาร์เรย์อาจล้าสมัยไปแล้วบางทีตัวหนา
awdz9nld

คำตอบ:


580

ในความเป็นจริงมันเป็นของหายากที่คุณต้องการใช้อาร์เรย์ ใช้List<T>ทุกครั้งที่คุณต้องการเพิ่ม / ลบข้อมูลอย่างแน่นอนเนื่องจากการปรับขนาดอาร์เรย์มีราคาแพง หากคุณทราบว่าข้อมูลมีความยาวคงที่และคุณต้องการปรับให้เหมาะสมขนาดเล็กด้วยเหตุผลเฉพาะบางอย่าง (หลังจากการเปรียบเทียบ) อาเรย์อาจมีประโยชน์

List<T>ข้อเสนอจำนวนมากการทำงานมากขึ้นกว่าอาร์เรย์ (แม้ว่า LINQ ปรับขึ้นเล็กน้อย) และเป็นเกือบตลอดทางเลือกที่เหมาะสม ยกเว้นparamsข้อโต้แย้งแน่นอน ;-P

ในฐานะเคาน์เตอร์ - List<T>เป็นมิติเดียว; โดยที่คุณมีอาร์เรย์สี่เหลี่ยม (ฯลฯ ) เหมือนint[,]หรือstring[,,]- แต่มีวิธีอื่นในการสร้างแบบจำลองข้อมูลดังกล่าว (ถ้าคุณต้องการ) ในรูปแบบวัตถุ

ดูสิ่งนี้ด้วย:

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

  • มันทำให้การขยับบิตได้มากดังนั้น a byte[]จึงค่อนข้างจำเป็นสำหรับการเข้ารหัส
  • ฉันใช้byte[]บัฟเฟอร์กลิ้งท้องถิ่นซึ่งฉันกรอกก่อนที่จะส่งลงไปที่กระแสพื้นฐาน (และ vv); เร็วกว่าBufferedStreamฯลฯ
  • มันใช้โมเดลวัตถุตามอาเรย์ ( Foo[]แทนที่จะList<Foo>) ภายในเนื่องจากขนาดจะถูกสร้างขึ้นครั้งเดียวและต้องเร็วมาก

แต่นี่เป็นข้อยกเว้นอย่างแน่นอน สำหรับการประมวลผลทั่วไปของธุรกิจการList<T>ชนะทุกครั้ง


8
อาร์กิวเมนต์เกี่ยวกับการปรับขนาดนั้นถูกต้องทั้งหมด อย่างไรก็ตามผู้คนชอบรายการแม้ว่าจะไม่จำเป็นต้องปรับขนาดก็ตาม สำหรับกรณีหลังนี้มีอาร์กิวเมนต์ที่เป็นตรรกะหรือไม่หรือมีอะไรมากกว่า "อาร์เรย์ล้าสมัย" หรือไม่?
เฟรเดอริหลอก

6
"ใช้รายการ <T> อย่างแน่นอนทุกครั้งที่คุณต้องการเพิ่ม / ลบข้อมูลเนื่องจากการปรับขนาดอาร์เรย์มีราคาแพง" รายการ <T> ใช้อาร์เรย์ภายใน คุณนึกถึง LinkedList <T> หรือไม่
dan-gph

14
คุณสมบัติเพิ่มเติม == มีความซับซ้อนมากขึ้น == ไม่ดียกเว้นว่าคุณต้องการคุณสมบัติเหล่านั้น คำตอบนี้แสดงเหตุผลว่าทำไมอาเรย์ของอาร์เรย์จึงดีกว่า
Eamon Nerbonne

12
@EamonNerbonne หากคุณไม่ได้ใช้คุณสมบัติเหล่านั้นฉันสามารถรับประกันได้เลยว่าพวกเขาจะไม่ทำร้ายคุณ ... แต่: จำนวนของคอลเลกชันที่ไม่ต้องการการกลายพันธุ์นั้นน้อยกว่าประสบการณ์ที่ฉันมี กลายพันธุ์
Marc Gravell

7
@MarcGravell: ขึ้นอยู่กับสไตล์การเขียนโค้ดของคุณ จากประสบการณ์ของฉันแทบจะไม่มีการเปลี่ยนแปลงคอลเลกชัน นั่นคือ; คอลเลกชันจะถูกดึงจากฐานข้อมูลหรือสร้างขึ้นจากแหล่งที่มาบางส่วน แต่การประมวลผลต่อไปจะทำโดยการสร้างคอลเลกชันใหม่เสมอ (เช่นแผนที่ / ตัวกรอง ฯลฯ ) แม้ในกรณีที่จำเป็นต้องมีการกลายพันธุ์ทางความคิดมันก็มีแนวโน้มที่จะง่ายที่สุดเพียงแค่สร้างคอลเลกชันใหม่ ฉันเคยกลายพันธุ์คอลเล็กชันเป็นการเพิ่มประสิทธิภาพและการเพิ่มประสิทธิภาพดังกล่าวมักจะอยู่ในระดับสูงและไม่เปิดเผยการกลายพันธุ์ให้กับผู้ใช้ API
Eamon Nerbonne

121

จริงๆแค่ตอบเพื่อเพิ่มลิงค์ที่ฉันประหลาดใจยังไม่ได้กล่าวถึง: บล็อกของ Eric Lippert ใน"อาร์เรย์ถือว่าค่อนข้างอันตราย"

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


2
ในที่สุดก็มาอ่านเรื่องนี้อีก 3 ปีต่อมาฮ่าฮ่า บทความดีดีบทความดีตอนนี้ :)
Spencer Ruport

21

แม้จะมีคำตอบอื่น ๆ ที่แนะนำList<T>คุณจะต้องใช้อาร์เรย์เมื่อจัดการ:

  • ข้อมูลภาพบิตแมป
  • โครงสร้างข้อมูลระดับต่ำอื่น ๆ (เช่นโปรโตคอลเครือข่าย)

1
ทำไมจึงต้องใช้โปรโตคอลเครือข่าย คุณไม่ควรใช้โครงสร้างที่กำหนดเองที่นี่และให้พวกเขาเป็นพิเศษ serializer หรือรูปแบบหน่วยความจำที่ชัดเจน? นอกจากนี้สิ่งที่พูดกับการใช้List<T>ที่นี่มากกว่าอาร์เรย์ไบต์?
Konrad Rudolph

8
@Konrad - ดีสำหรับการเริ่ม Stream.Read และ Stream.Write ทำงานร่วมกับ byte [] เช่นเดียวกับการเข้ารหัส ฯลฯ ...
Marc Gravell

12

ถ้าคุณไม่เกี่ยวข้องกับประสิทธิภาพจริงๆและโดยที่ฉันหมายถึง "ทำไมคุณถึงใช้. Net แทน C ++" คุณควรติดกับ List <> ง่ายต่อการบำรุงรักษาและทำงานสกปรกทั้งหมดในการปรับขนาดอาร์เรย์เบื้องหลังสำหรับคุณ (หากจำเป็นรายการ <> ค่อนข้างฉลาดในการเลือกขนาดอาร์เรย์จึงไม่จำเป็นต้องทำตามปกติ)


15
"ทำไมคุณถึงใช้. Net แทน C ++" XNA
Bengt

6

ควรใช้อาร์เรย์ในการตั้งค่าเป็น List เมื่อความไม่สามารถเปลี่ยนแปลงได้ของคอลเลกชันเองเป็นส่วนหนึ่งของสัญญาระหว่างรหัสลูกค้าและผู้ให้บริการ

ตัวอย่างเช่น,

var str = "This is a string";
var strChars = str.ToCharArray();  // returns array

เป็นที่ชัดเจนว่าการดัดแปลงของ "strChars" จะไม่กลายพันธุ์วัตถุ "str" ​​ดั้งเดิมโดยไม่คำนึงถึงความรู้ระดับการใช้งานของประเภทพื้นฐานของ "str"

แต่สมมติว่า

var str = "This is a string";
var strChars = str.ToCharList();  // returns List<char>
strChars.Insert(0, 'X');

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


ฉันค่อนข้างใหม่กับ C # แต่ไม่ชัดเจนสำหรับฉันว่าทำไมการส่งคืนรายการจึงแนะนำให้ความไม่แน่นอนของข้อมูลดั้งเดิมในลักษณะที่การส่งคืนอาร์เรย์จะไม่ ฉันจะได้ว่าวิธีการที่ชื่อขึ้นต้นด้วยToกำลังจะสร้างวัตถุที่ไม่มีความสามารถในการปรับเปลี่ยนอินสแตนซ์ดั้งเดิมซึ่งตรงข้ามกับstrChars as char[]ที่ถ้าถูกต้องจะแนะนำให้คุณสามารถแก้ไขวัตถุต้นฉบับ
ทิม MB

@TimMB มีการเปลี่ยนแปลงไม่ได้ของคอลเลกชัน (ไม่สามารถเพิ่มหรือรายการระยะไกล) และการเปลี่ยนแปลงไม่ได้ของรายการในคอลเลกชัน ฉันหมายถึงหลังในขณะที่คุณอาจทำให้ทั้งสอง การส่งคืนอาร์เรย์ทำให้ลูกค้ามั่นใจว่าจะไม่สามารถเพิ่ม / ลบรายการได้ ถ้าเป็นเช่นนั้นมันจะจัดสรรอาร์เรย์อีกครั้งและมั่นใจได้ว่าจะไม่ส่งผลกระทบต่อต้นฉบับ การส่งคืนรายการไม่มีการรับรองดังกล่าวและอาจได้รับผลกระทบดั้งเดิม (ขึ้นอยู่กับการนำไปใช้) การเปลี่ยนไอเท็มภายในคอลเล็กชัน (ไม่ว่าจะเป็นอาเรย์หรือรายการ) อาจส่งผลกระทบต่อต้นฉบับได้หากประเภทของรายการนั้นไม่ใช่โครงสร้าง
Herman Schoenfeld

ขอบคุณสำหรับการชี้แจง ฉันยังสับสนอยู่ (อาจเป็นเพราะฉันมาจากโลก C ++) หากstrภายในใช้อาเรย์และToCharArrayส่งกลับการอ้างอิงไปยังอาเรย์นี้ลูกค้าสามารถกลายพันธุ์ได้strโดยการเปลี่ยนองค์ประกอบของอาเรย์นั้นแม้ว่าขนาดจะยังคงอยู่ แต่คุณเขียน 'เป็นที่ชัดเจนว่าการดัดแปลงของ "strChars" จะไม่กลายพันธุ์วัตถุ "str" ​​ดั้งเดิม ฉันหายไปนี่อะไร จากสิ่งที่ฉันเห็นในทั้งสองกรณีลูกค้าอาจเข้าถึงการเป็นตัวแทนภายในและไม่ว่าจะเป็นประเภทใดก็ตามสิ่งนี้จะทำให้เกิดการกลายพันธุ์บางอย่าง
ทิม MB

3

ถ้าฉันรู้ว่าวิธีการหลายองค์ประกอบที่ฉันจะต้องบอกว่าผมต้อง 5 องค์ประกอบและคนเดียวที่เคย 5 องค์ประกอบแล้วฉันจะใช้อาร์เรย์ มิฉะนั้นฉันจะใช้รายการ <T>


1
ทำไมคุณไม่ใช้ List <T> ในกรณีที่คุณรู้จำนวนองค์ประกอบ?
โอลิเวอร์

3

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

ดูhttp://msdn.microsoft.com/en-us/library/ms379570(v=vs.80).aspx#datastructures20_1_topic5สำหรับข้อมูลเพิ่มเติมเกี่ยวกับรายชื่อใน C # System.Collections.Generic.List<T>หรือเพียงแค่แยก

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

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


1
สวัสดีคุณช่วยอธิบายได้ไหมว่า "เวลาในการค้นหาของรายการจะเป็น O (n)" เป็นจริงหรือไม่ เท่าที่ฉันรู้ List <T> ใช้อาร์เรย์อยู่เบื้องหลัง
แมลงปอ

1
@ Dragonfly คุณพูดถูก แหล่ง ในตอนนั้นฉันคิดว่าการติดตั้งนั้นใช้พอยน์เตอร์ แต่ฉันได้เรียนรู้อย่างอื่น จากลิงก์ด้านบน: 'การดึงค่าของคุณสมบัตินี้เป็นการดำเนินการ O (1); การตั้งค่าคุณสมบัติเป็นการดำเนินการ O (1) '
Sune Rievers

2

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

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


1

อีกสถานการณ์ที่ยังไม่ได้กล่าวถึงคือเมื่อจะมีรายการจำนวนมากซึ่งแต่ละรายการประกอบด้วยตัวแปรที่เกี่ยวข้อง แต่ไม่เกี่ยวข้องกันติดอยู่ด้วยกัน (เช่นพิกัดของจุดหรือจุดยอดของรูปสามเหลี่ยมสามมิติ) อาร์เรย์ของโครงสร้างฟิลด์ที่เปิดเผยจะช่วยให้องค์ประกอบของมันสามารถแก้ไขได้อย่างมีประสิทธิภาพ "ในสถานที่" - สิ่งที่เป็นไปไม่ได้กับประเภทคอลเลกชันอื่น ๆ เนื่องจากอาเรย์ของโครงสร้างเก็บองค์ประกอบไว้อย่างต่อเนื่องในแรมการเข้าถึงลำดับของอิลิเมนต์เรียงลำดับจึงทำได้อย่างรวดเร็ว ในสถานการณ์ที่รหัสจะต้องมีการส่งผ่านลำดับจำนวนมากผ่านอาร์เรย์อาร์เรย์ของโครงสร้างอาจมีประสิทธิภาพสูงกว่าอาร์เรย์หรือคอลเลกชันอื่น ๆ ของการอ้างอิงวัตถุคลาสโดยปัจจัย 2: 1; เพิ่มเติม

แม้ว่าอาร์เรย์จะไม่สามารถปรับขนาดได้ แต่ก็ไม่ยากที่จะให้มีการอ้างอิงอาร์เรย์เก็บรหัสพร้อมกับจำนวนองค์ประกอบที่ใช้งานอยู่ อีกทางเลือกหนึ่งที่สามารถเขียนโค้ดได้อย่างง่ายดายสำหรับประเภทที่ประพฤติเหมือนList<T>แต่สัมผัสการจัดเก็บการสนับสนุนของมันจึงช่วยให้หนึ่งที่จะพูดอย่างใดอย่างหนึ่งหรือMyPoints.Add(nextPoint); MyPoints.Items[23].X += 5;หมายเหตุที่หลังจะไม่จำเป็นต้องโยนยกเว้นถ้ารหัสพยายามที่จะเข้าถึงเกินสิ้นของรายการ List<T>แต่การใช้งานมิฉะนั้นจะแนวคิดค่อนข้างคล้ายกับ


สิ่งที่คุณอธิบายคือรายการ <> มีตัวสร้างดัชนีเพื่อให้คุณสามารถเข้าถึงอาร์เรย์ต้นแบบได้โดยตรงและ List <> จะรักษาขนาดให้คุณ
Carl

@Carl: ให้เช่นอาจเป็นไปได้สำหรับรหัสที่จะพูดเช่นPoint[] arr; arr[3].x+=q;ใช้เช่นมันจะเป็นสิ่งจำเป็นที่จะพูดแทนList<Point> list Point temp=list[3]; temp.x+=q; list[3]=temp;มันจะเป็นประโยชน์ถ้ามีวิธีการList<T> Update<TP>(int index, ActionByRefRef<T,TP> proc, ref TP params)และคอมไพเลอร์สามารถเปลี่ยนlist[3].x+=q;เป็น{list.Update(3, (ref int value, ref int param)=>value+=param, ref q);แต่ไม่มีคุณสมบัติดังกล่าวอยู่
supercat

ข่าวดี. มันได้ผล. list[0].X += 3;จะเพิ่ม 3 เข้าไปในคุณสมบัติ X ขององค์ประกอบแรกของรายการ และlistเป็นList<Point>และPointเป็นคลาสที่มีคุณสมบัติ X และ Y
Carl

1

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


0

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

เวลาส่วนใหญ่ในรหัสที่ได้รับการจัดการคุณจะต้องชื่นชอบคอลเลกชันที่ง่ายต่อการใช้งานมากที่สุดเท่าที่จะทำได้โดยไม่ต้องกังวลเกี่ยวกับการปรับให้เหมาะสมแบบไมโคร


0

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

ที่ถูกกล่าวว่าฉันใช้รายการบ่อยกว่าอาร์เรย์ในทางปฏิบัติ แต่พวกเขาแต่ละคนมีสถานที่ของพวกเขา

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


0

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

List<URLDTO> urls = new List<URLDTO>();

urls.Add(new URLDTO() {
    key = "wiki",
    url = "https://...",
});

urls.Add(new URLDTO()
{
    key = "url",
    url = "http://...",
});

urls.Add(new URLDTO()
{
    key = "dir",
    url = "https://...",
});

// convert a list into an array: URLDTO[]
return urls.ToArray();

0

เนื่องจากไม่มีใครพูดถึง: ใน C # อาร์เรย์เป็นรายการ MyClass[]และList<MyClass>ใช้งานทั้งสองIList<MyClass>อย่าง (เช่นvoid Foo(IList<int> foo)สามารถเรียกว่าชอบFoo(new[] { 1, 2, 3 })หรือFoo(new List<int> { 1, 2, 3 }) )

ดังนั้นหากคุณกำลังเขียนวิธีการที่ยอมรับList<MyClass>ว่าเป็นข้อโต้แย้ง แต่ใช้เพียงส่วนย่อยของคุณสมบัติคุณอาจต้องการประกาศเป็นIList<MyClass>แทนเพื่อความสะดวกของผู้โทร

รายละเอียด:


"ใน C # อาร์เรย์คือรายการ"นั่นไม่เป็นความจริง อาร์เรย์ไม่ได้เป็นListเพียงใช้IListอินเทอร์เฟซเท่านั้น
รูฟัส L

-1

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

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


1
หากคุณมีรายการของรายการและคุณต้องการแสดงรายการนั้นมีอะไรผิดปกติเพียงแค่ใช้รายการที่คุณมีอยู่แล้ว อาเรย์จะเสนออะไรที่นี่?
Marc Gravell

1
และสำหรับ "การสร้างรายการที่จะใช้งานโดยฟังก์ชั่นหรือบริการอื่น ๆ " ที่จริงแล้วฉันต้องการบล็อกตัววนซ้ำด้วยIEnumerable<T>- จากนั้นฉันสามารถสตรีมวัตถุมากกว่าบัฟเฟอร์พวกเขา
Marc Gravell

-1

เป็นมูลค่าการกล่าวขวัญถึงความสามารถในการคัดเลือกนักแสดงทันที

interface IWork { }
class Foo : IWork { }

void Test( )
{
    List<Foo> bb = new List<Foo>( );
    // Error: CS0029 Cannot implicitly convert type 'System.Collections.Generic.List<Foo>' to 'System.Collections.Generic.List<IWork>'
    List<IWork> cc = bb; 

    Foo[] bbb = new Foo[4];
    // Fine
    IWork[] ccc = bbb;
}

ดังนั้นArrayให้ความยืดหยุ่นมากขึ้นเล็กน้อยเมื่อใช้ในประเภทส่งคืนหรืออาร์กิวเมนต์สำหรับฟังก์ชัน

IWork[] GetAllWorks( )
{
    List<Foo> fooWorks = new List<Foo>( );
    return fooWorks.ToArray( ); // Fine
}

void ExecuteWorks( IWork[] works ) { } // Also accept Foo[]

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