มีเหตุผลที่จะใช้อาร์เรย์เมื่อรายการพร้อมใช้งานหรือไม่? [ปิด]


30

ดูเหมือนว่าList<T>ใน C # สามารถทำทุกอย่างที่อาเรย์สามารถทำได้และอื่น ๆ อีกมากมายและดูเหมือนว่าในหน่วยความจำและประสิทธิภาพก็มีประสิทธิภาพเช่นเดียวกับอาเรย์

เหตุใดฉันจึงต้องการใช้อาร์เรย์

เห็นได้ชัดว่าฉันไม่ได้ถามเกี่ยวกับกรณีที่ API หรือข้อ จำกัด ภายนอกอื่น ๆ (เช่นฟังก์ชั่นหลัก) ต้องการให้ฉันใช้อาร์เรย์ ... ฉันแค่ถามเกี่ยวกับการสร้างโครงสร้างข้อมูลใหม่ในรหัสของฉันเอง


56
ที่จะใช้List<T>
วงล้อประหลาด

43
is also just as efficient in memory and performance as an array- อืม คุณได้ความคิดนั้นมาจากไหน
Oded

12
มีหลายมิติเช่นvar test = new string[5,5];)
Knerd

7
นอกจากนี้ยังมีอาร์เรย์ [] ที่ใช้กันทั่วไป
SBoss

11
สำหรับ C # โดยเฉพาะเอริค Lippert เขียนเกี่ยวกับเรื่องนี้ในblogs.msdn.com/b/ericlippert/archive/2008/09/22/...
Mephy

คำตอบ:


26

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

ประการแรกอาร์เรย์ทั้งหมดเป็นโครงสร้างดั้งเดิมดังนั้นอาร์เรย์จึงเร็วและมีประสิทธิภาพมากกว่ารายการ <> แน่นอนดังนั้นอาร์กิวเมนต์ของคุณไม่เป็นความจริง Array ยังมีอยู่ทุกหนทุกแห่งและเป็นที่รู้จักของนักพัฒนาที่ใช้ภาษาและแพลตฟอร์มที่ต่าง

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

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

และบางครั้งก็ง่ายกว่าที่จะทำการพอร์ตชิ้นส่วนของรหัสที่ใช้อาร์เรย์แทนชนิดที่ขึ้นกับกรอบงาน


4
อาเรย์เป็นอย่างไร "เร็วกว่า" โดยพิจารณาว่าList<T>จะมีการใช้งานอาเรย์อย่างไร? หากคุณรู้ว่าองค์ประกอบนับไว้ล่วงหน้า (ซึ่งคุณต้องรู้เมื่อใช้อาร์เรย์) คุณสามารถใช้ความรู้นั้นเมื่อเริ่มต้นรายการเช่นกัน
Theodoros Chatzigiannakis

1
@TheodorosChatzigiannakis เมื่อใช้อาร์เรย์เราจะจัดสรรหน่วยความจำและทำการมอบหมายงานธรรมดา malloc () ไม่มีค่าใช้จ่าย เมื่อคุณใช้รายการ <> คุณจะ "เพิ่ม" รายการและเมื่อเพิ่มรายการรายการ <> จะทำการตรวจสอบขอบเขตและเรียกวิธีการ SureCapacity ซึ่งจะคัดลอกเนื้อหาไปยังอาร์เรย์ที่เพิ่งจัดสรรใหม่หากความจุปัจจุบันไม่เพียงพอ หมายความว่าหากคุณไม่ต้องการจัดสรรหน่วยความจำใหม่แบบไดนามิกประสิทธิภาพของรายการจะไม่ดีเท่าอาเรย์
Mert Akcakaya

4
สิ่งที่คุณกำลังจะบอกว่าถูกต้อง แต่ก็สันนิษฐานว่าทั้งที่เราไม่ทราบว่านับองค์ประกอบก่อน (ในกรณีที่อาร์เรย์ไม่ได้อยู่แล้วที่มีประโยชน์) หรือที่เราทำรู้ว่านับองค์ประกอบก่อน แต่เราจงใจไม่ได้ใช้ ในกรณีของรายการ ถ้าเราทำใช้นับองค์ประกอบในการเริ่มต้นรายการที่มีความจุที่ต้องการเราได้รับการจัดสรรเพียงหนึ่งอาร์เรย์ (จนกว่าจะถึงกำลังการผลิตที่) ทำให้เราต้องจ่ายค่าใช้จ่ายในการปฏิบัติงานเดียวกัน การดำเนินการทั่วไปอื่น ๆ ทั้งหมดมีค่าเท่ากัน (การค้นหาการดึงข้อมูลโดยดัชนีการมอบหมายโดยดัชนี) ยกเว้นการเพิ่มเพิ่มเติม (ซึ่งอาร์เรย์ไม่มีทั้งหมด)
Theodoros Chatzigiannakis

3
@TheodorosChatzigiannakis: อาร์เรย์มีเร็วกว่ารายการ เพียงใช้มาตรฐานง่ายๆในการตรวจสอบ
Mehrdad

1
@TheodorosChatzigiannakis ใช่ แต่ยังมีการตรวจสอบขอบเขต
Mert Akcakaya

18

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

struct EvilMutableStruct { public double X; } // don't do this

EvilMutableStruct[] myArray = new EvilMutableStruct[1];
myArray[0] = new EvilMutableStruct()
myArray[0].X = 1; // works, this modifies the original struct

List<EvilMutableStruct> myList = new List<EvilMutableStruct>();
myList.Add(new EvilMutableStruct());
myList[0].X = 1; // does not work, the List will return a *copy* of the struct

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


อย่างจริงจังมากขึ้นคุณจะต้องอาร์เรย์ถ้าคุณต้องการที่จะผ่านองค์ประกอบโดยกรอบอ้างอิง กล่าวคือ

Interlocked.Increment(ref myArray[i]);  // works
Interlocked.Increment(ref myList[i]);   // does not work, you can't pass a property by reference

ซึ่งมีประโยชน์สำหรับรหัส threadsafe ที่ไม่ล็อค


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

double[] myArray = new double[1000]; // contains 1000 '0' values
                                     // without further initialisation

List<double> myList = new List<double>(1000) // internally contains 1000 '0' values, 
                                             // since List uses an array as backing storage, 
                                             // but you cannot access those
for (int i =0; i<1000; i++) myList.Add(0);   // slow and inelegant

(โปรดทราบว่ามันเป็นไปได้ที่จะใช้ตัวสร้างสำหรับรายการที่ทำเช่นเดียวกันเป็นเพียงที่ c # ไม่เสนอคุณสมบัตินี้)


คุณต้องการอาเรย์ถ้าคุณต้องการคัดลอกบางส่วนของคอลเลกชันได้อย่างมีประสิทธิภาพ

Array.Copy(array1, index1, array2, index2, length) // can't get any faster than this

double[,] array2d = new double[10,100];
double[] arraySerialized = new double[10*100];
Array.Copy(array2d, 0, arraySerialized, 0, arraySerialized.Length);
// even works for different dimensions

(อีกครั้งนี่คือสิ่งที่สามารถนำไปใช้กับรายการได้เช่นกัน แต่คุณลักษณะนี้ไม่มีอยู่ใน c #)


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

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

หากมีความประสงค์ที่จะใช้การเก็บรวบรวมของการอ้างอิงวัตถุที่ไม่แน่นอนเป็นกลุ่มของตัวแปรอิสระที่เป็นอิสระหนึ่งจะต้องสร้างและรักษาค่าคงที่ว่าแต่ละองค์ประกอบระบุวัตถุที่ไม่มีการอ้างอิงที่ไม่ใช่ชั่วคราวอื่น ๆ ที่ใดก็ได้ในจักรวาล สามารถทำได้อย่างแน่นอน (และบ่อยครั้ง) แต่ไม่มีอะไรในภาษาหรือกรอบที่จะช่วยโปรแกรมเมอร์ในการสนับสนุนค่าคงที่ ในทางตรงกันข้ามอาร์เรย์ที่มีความยาว 100 ชนิดของโครงสร้างที่มีสี่อินสแตนซ์ฟิลด์จะสรุปตัวแปรอิสระโดยอัตโนมัติ 400 รายการ
supercat

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

15

เหตุใดฉันจึงต้องการใช้อาร์เรย์

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

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


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

11
ไม่ใช่เรื่องผิดปกติที่จะต้องจัดการกับองค์ประกอบจำนวนหนึ่ง หากคุณทำงานกับคะแนน 3 มิติคุณอาจจะไม่ทำงานกับคะแนน 5D ที่จุดใด ๆ ในอนาคต ปัญหาที่ใหญ่กว่าของอาร์เรย์คือพวกมันไม่แน่นอนและไม่มีป้ายกำกับที่สะดวกติดอยู่กับองค์ประกอบ
Doval

3
@JanDvorak รายการสามารถหดหรือขยายและทำให้ไม่เหมาะสมในบริบทใด ๆ ที่เกี่ยวข้องกับองค์ประกอบจำนวนคงที่
Doval

9
ไม่ค่อย? ไม่ใช่ทุกคนที่ทำงานกับโครงข่ายขององค์กรที่มีความซับซ้อนสูงพิเศษที่กำหนดค่าได้ยาก
whatsisname

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

9

คำถามของคุณได้รับคำตอบจริงแล้วก่อนหน้านี้

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

มันไม่ใช่ จากคำถามที่ฉันเชื่อมโยง:

List/foreach:  3054ms (589725196)
Array/foreach: 1860ms (589725196)

อาร์เรย์มีความรวดเร็วเป็นสองเท่าในบางกรณีที่สำคัญ ฉันมั่นใจว่าการใช้งานหน่วยความจำนั้นแตกต่างกันเล็กน้อย

เนื่องจากหลักฐานหลักของคำถามของคุณแพ้ดังนั้นฉันจึงถือว่าคำตอบนี้เป็นคำถามของคุณ นอกจากนี้บางครั้งอาร์เรย์ยังบังคับให้คุณใช้ Win32 API หรือ shader ของ GPU ของคุณหรือบางไลบรารีที่ไม่ใช่ DotNet

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

คำถามและคำตอบเพิ่มเติมเกี่ยวกับ Stack Overflow ในหัวข้อนี้:


น่าสนใจว่าจุดคำตอบออกมาว่าถ้าคุณใช้สมัยเก่าลูปที่จัดทำดัชนี ( สำหรับแทนforeach ) แตกต่างประสิทธิภาพน้อยที่สุด
user949300

3

นอกเหนือจากเหตุผลที่ระบุไว้ในคำตอบอื่น ๆ ตัวอักษรอาร์เรย์ใช้ตัวอักษรน้อยลงในการประกาศ:

var array = new [] { "A", "B", "C" };
var list = new List<string>() { "A", "B", "C" };

การใช้อาร์เรย์แทนListทำให้โค้ดสั้นลงเล็กน้อยและอ่านได้ง่ายขึ้นในกรณีที่ (1) คุณต้องผ่านIEnumerable<T>ตัวอักษรใด ๆหรือ (2) ซึ่งการทำงานอื่น ๆ ของListไม่สำคัญและคุณจำเป็นต้องใช้รายการบางอย่าง ตามตัวอักษร

ฉันทำสิ่งนี้เป็นครั้งคราวในการทดสอบหน่วย


1
ใช่เพียงเพื่อเพิ่ม นอกจากนี้คุณยังต้องทำงานกับ IList <T> ด้วย
Esben Skov Pedersen

+1, บ่อยครั้งที่ฉันมีการดำเนินการสำหรับวัตถุสองประเภทที่เหมือนกันซึ่งไม่ได้อยู่ในชุดสะสม ง่ายสั้นและชัดเจนในการเขียนforeach( var x in new []{ a, b, c ) ) DoStuff( x )หรือnew []{ a, b, c ).Select( ... )อื่น ๆ
stijn

3

นี่เป็นมุมมองของ OO อย่างเคร่งครัด

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

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

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

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


3

สิ่งนี้มีไว้สำหรับภาษาอื่นที่มีรายการเช่นกัน (เช่น Java หรือ Visual Basic) มีหลายกรณีที่คุณจำเป็นต้องใช้อาร์เรย์เนื่องจากวิธีการส่งกลับอาร์เรย์แทนรายการ

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


1
หลายภาษาไม่ได้มีรายการแยกต่างหากและคอลเลกชันอาร์เรย์ ในทางกลับกันการใช้list<T>ตำแหน่งที่vector<T>จะทำงานเป็นความคิดที่เลวร้ายใน C / C ++
Gort the Robot

1
"เนื่องจากเมธอดส่งคืนอาร์เรย์" - นี่เป็นความผิดพลาดของ Java บังคับให้โปรแกรมเมอร์เขียนรหัสด้วย "Arrays.asList (x)" อย่างน้อย T [] ควรใช้ Iterable <T>
kevin cline

4
@StevenBurnap - มันร้ายกาจอย่างมากใน C เพราะไม่มีทางที่จะคอมไพล์โค้ดนั้น
Pete Becker

@PeteBecker การแสดงออกvector<T> x รวบรวมเพียงที่ดีสำหรับฉันใน C :-)
svick

ขอโทษนะฉันหมายถึง C list<T>มือรีดเทียบเท่า โดยทั่วไปฉันได้เห็นปัญหาด้านประสิทธิภาพมากมายที่เกิดจากนักพัฒนาเพียงแค่ใช้รายการตามค่าเริ่มต้นเมื่ออาร์เรย์เป็นตัวเลือกที่ดีกว่า
Gort the Robot

1

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

  1. ฉันรู้แน่ชัดว่ามีช่องรายการสินค้าคงคลังที่เปิดอยู่จำนวนเท่าใดที่วัตถุเกมมีโดยการดูและดูว่าช่องใดเป็นช่องว่าง
  2. ฉันรู้แน่ชัดว่าแต่ละดัชนีมีรายการอะไร
  3. มันยังคงเป็นอาร์เรย์ "พิมพ์" (รายการ [] คลังโฆษณา) ดังนั้นฉันสามารถเพิ่ม / ลบวัตถุประเภท "รายการ"

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


1

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

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

สิ่งนี้ค่อนข้างคล้ายกับ "จำเป็นต้องไปที่ใด?" ในภาษาสมัยใหม่ที่สมเหตุสมผลไม่จำเป็นเลย แต่ถ้าคุณลอก abstractions ออกในบางจุดนั่นคือทั้งหมดที่มีให้คุณนั่นคือวิธีเดียวที่จะใช้ abstractions เหล่านี้ได้คือมีคุณสมบัติ 'ไม่จำเป็น' (แน่นอนว่าการเปรียบเทียบไม่สมบูรณ์แบบฉันไม่คิดว่ามีใครบอกว่าอาร์เรย์เป็นแบบฝึกการเขียนโปรแกรมที่ไม่ดีพวกเขาเข้าใจและคิดได้ง่าย)


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

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

0

ความเข้ากันได้แบบดั้งเดิม

ประสบการณ์ส่วนตัวทุกรูปแบบ:

โปรแกรมเมอร์เก่า - เพื่อนร่วมงานของฉันใช้อาร์เรย์ทุกที่ทำมานานกว่า 30 ปีโชคดีที่เปลี่ยนใจด้วยไอเดียที่แปลกใหม่ของคุณ

รหัสดั้งเดิม - foo (แถบอาร์เรย์ []) ให้แน่ใจว่าคุณสามารถใช้ฟังก์ชัน list / vector / collection toarray แต่ถ้าคุณไม่ได้ใช้คุณสมบัติเพิ่มเติมใด ๆ ของมันจะง่ายต่อการใช้อาร์เรย์เพื่อเริ่มต้นบ่อยครั้งอ่านได้โดยไม่ต้องสลับประเภท

Legacy boss - เจ้านายของฉันเป็นโปรแกรมเมอร์ที่ดีก่อนที่เธอจะเข้าสู่การจัดการเมื่อหลายปีก่อนและยังคงคิดว่าเธอทันสมัยอยู่เสมอ“ กำลังใช้อาร์เรย์” สามารถจบการประชุมได้


3
เพื่อนร่วมงานที่อายุต่ำกว่า 20 ปีและเจ้านายที่ต้องการทราบว่าคุณใช้ข้อมูลประเภทใด ... ฉันรักไซต์นี้เพื่อเตือนตัวเองว่างานของฉันจะยิ่งแย่ลงแค่ไหน
JoelFan

1
ประมาณ 40% ของสิ่งที่เราทำคือการออกแบบแบบฝังที่การอภิปรายถูกจัดขึ้นเป็น KB เขาชอบที่จะบอกฉันว่าไม่ล้าสมัยนะครับพวกเขาชอบมาก ๆ
Skeith

0

1) ไม่มีรายการเวอร์ชันหลายมิติ หากข้อมูลของคุณมีมากกว่าหนึ่งมิติจะไม่มีประสิทธิภาพในการใช้รายการ

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

สำหรับกรณีที่รุนแรงพิจารณา Minecraft (ใช่มันไม่ได้เขียนใน C # ด้วยเหตุผลเดียวกันนี้)



0

อาเรย์ 100 องค์ประกอบของบางประเภท T ห่อหุ้มตัวแปรอิสระ 100 ตัวของประเภท T หาก T เกิดขึ้นเป็นประเภทค่าที่มีเขตข้อมูลสาธารณะที่ไม่แน่นอนของประเภท Q และหนึ่งในประเภท R จากนั้นแต่ละองค์ประกอบของอาร์เรย์จะ encapsulate ตัวแปรอิสระ ของประเภท Q และ R อาเรย์โดยรวมจึงจะแค็ปซูล 100 ตัวแปรอิสระของประเภท Q และ 100 ตัวแปรอิสระประเภท R; ตัวแปรใด ๆ เหล่านั้นสามารถเข้าถึงได้แบบเอกเทศโดยไม่มีผลกระทบใด ๆ ไม่มีประเภทคอลเลกชันใด ๆ นอกเหนือจากอาร์เรย์ที่สามารถอนุญาตให้ฟิลด์ของโครงสร้างใช้เป็นตัวแปรอิสระได้

ถ้า T เกิดขึ้นแทนที่จะเป็นประเภทคลาสที่มีฟิลด์ที่ไม่แน่นอนสาธารณะของชนิด Q และ R แต่ละองค์ประกอบของอาเรย์จะมีการอ้างอิงเพียงอย่างเดียวที่ใดก็ได้ในจักรวาลไปยังอินสแตนซ์ของTและหากไม่มีองค์ประกอบใดของอาเรย์ ได้รับการแก้ไขเพื่อระบุวัตถุที่มีการอ้างอิงภายนอกใด ๆ อยู่แล้วอาเรย์จะได้อย่างมีประสิทธิภาพแค็ปซูล 100 ตัวแปรอิสระของประเภท Q และ 100 ตัวแปรอิสระของอาร์ประเภทคอลเลกชันอื่น ๆ สามารถเลียนแบบพฤติกรรมของอาเรย์ดังกล่าว ของอาร์เรย์คือการแค็ปซูล 100 ตัวแปรของประเภท Q และ 100 ของ type R การห่อหุ้มแต่ละคู่ของตัวแปรในวัตถุคลาสของตัวเองเป็นวิธีที่มีราคาแพงในการทำเช่นนั้น เพิ่มเติมใช้อาร์เรย์หรือคอลเลกชันของประเภทคลาสที่ไม่แน่นอน ว่าตัวแปรที่ระบุโดยองค์ประกอบมากมายอาจจะไม่เป็นอิสระ

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


0

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

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

จากนั้นมีการใช้งานรายการเช่น ArrayList ซึ่งใช้รายการโดยใช้อาร์เรย์ มันมีประโยชน์เบื้องต้นที่จะมี


2
คำถามที่ถามโดยเฉพาะเกี่ยวกับประเภท. Net List<T>ซึ่งไม่ได้ดำเนินการโดยใช้รายการที่เชื่อมโยง แต่ใช้อาร์เรย์ (มันเทียบเท่ากับArrayList<T>ใน Java)
svick

-2

ต่อไปนี้เป็นคำแนะนำบางอย่างที่คุณสามารถใช้เมื่อเลือกและเมื่อเลือกArrayList

  • ใช้Arrayเมื่อกลับมาจากวิธีการ
  • ใช้Listเป็นตัวแปรเมื่อคุณสร้างค่าส่งคืน (ภายในเมธอด) จากนั้นใช้.ToArray()เมื่อกลับจากวิธีการ

โดยทั่วไปใช้Arrayเมื่อคุณไม่ต้องการให้ผู้บริโภคเพิ่มรายการลงในคอลเลกชัน ใช้Listเมื่อคุณต้องการให้ผู้บริโภคเพิ่มรายการในคอลเลกชัน

Arrayมีไว้สำหรับจัดการกับคอลเลกชัน "คงที่" ในขณะที่Listมีไว้สำหรับจัดการกับคอลเลกชัน "แบบไดนามิก"


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

@Jules ฉันพบว่านักพัฒนาซอฟต์แวร์มีความสำคัญมากกว่าการปรับให้เหมาะสมแบบไมโคร ฉันไม่เคยมีปัญหาด้านประสิทธิภาพในระดับนี้
Daniel Lidström

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

@Jules ฉันคิดว่ามันเป็นความชอบของคุณเอง ฉันชอบที่จะรักษาค่ากลับมาเป็นค่าคงที่เช่นฉันชอบที่จะใช้แทนArray Listดีใจที่ได้ยินความคิดของคุณ!
Daniel Lidström

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