รายการอ่านอย่างเดียวหรือรายการที่ไม่สามารถแก้ไขได้ใน. NET 4.0


100

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

ข้อดีอย่างหนึ่งที่ Java มีเหนือ C # คือในรูปแบบของเมธอดCollections.unmodifiablelist (list)ซึ่งดูเหมือนว่าจะค้างชำระเป็นเวลานานใน IList <T> หรือ List <T>

การใช้IEnumerable<T>เป็นวิธีแก้ปัญหาที่ง่ายที่สุด - ToListสามารถใช้และส่งคืนสำเนาได้


ดูเหมือนวิธีเดียวที่แท้จริงในการอ่านอย่างเดียวList<T>คือการเขียนของคุณเองไม่มีคลาสในตัวที่ฉันรู้ว่ารองรับคุณสมบัติ "อ่านอย่างเดียว" ทั้งหมดList<T>นอกกรอบเช่นContainsแบบสอบถาม LINQ เป็นต้น
jrh

คำตอบ:


146

คุณกำลังมองหาReadOnlyCollectionซึ่งมีมาตั้งแต่. NET2

IList<string> foo = ...;
// ...
ReadOnlyCollection<string> bar = new ReadOnlyCollection<string>(foo);

หรือ

List<string> foo = ...;
// ...
ReadOnlyCollection<string> bar = foo.AsReadOnly();

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


1
ตอนนี้ฉันรู้สึกโง่นิดหน่อยที่ถามคำถามนี้ - และไม่รู้เกี่ยวกับ ReadOnlyCollection
Chris S

54
ไม่เป็น - ฉันก็ไม่เหมือนกันเมื่อฉันไปหาสิ่งเดียวกันและพบคำถามของคุณ
Roland Tepp

9
นั่นเป็นคลาสที่หายากและน่ารำคาญ อยู่ในเนมสเปซ System.Collections.ObjectModel แทน System.Collections.Generic ที่ฉันคาดหวังว่าจะพบ ฉันคิดว่าเป็นเพราะนั่นคือที่มาก่อนที่จะมีเนมสเปซทั่วไป ฉันยังคงคาดหวังว่าคลาสฐานจะยังคงอยู่ใน ObjectModel และคลาสทั่วไปที่จะเพิ่มลงใน Generic ฉันคิดว่าพวกเขามีเหตุผล แต่ฉันคิดว่ามันน่ารำคาญ
BlueMonkMN

5
@BlueMonkMN: โปรดอ่านบทความนี้เพื่อดูว่าเหตุใดจึงแยกออกจากคอลเล็กชันเนมสเปซทั่วไป
Uchitha

7
แต่นั่นไม่ใช่รายการ แต่เป็นคอลเล็กชัน ดังนั้นหากคุณใช้คุณจะต้องแก้ไขโค้ดทั้งหมดเพื่อใช้ Collection แทน List
Roman Zabicki

13

สำหรับผู้ที่ต้องการใช้อินเทอร์เฟซ: .NET 4.5 จะเพิ่มIReadOnlyListอินเทอร์เฟซทั่วไปซึ่งใช้งานโดยList<T>ตัวอย่างเช่น

มันคล้ายกับIReadOnlyCollectionและเพิ่มItemคุณสมบัติตัวทำดัชนี



11

หากรูปแบบที่พบบ่อยที่สุดของรายการคือการวนซ้ำองค์ประกอบทั้งหมดIEnumerable<T>หรือIQueryable<T>สามารถทำหน้าที่เป็นรายการแบบอ่านอย่างเดียวได้อย่างมีประสิทธิภาพเช่นกัน


4
หากคุณเปิดเผยรายการของคุณเป็น IEnumerable ผู้บริโภคก็สามารถส่งกลับไปที่ List และแก้ไขได้
JulianR

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

5
คุณไม่ได้แก้ไขรายการต้นฉบับด้วยการโทรToList()เพียงแค่สำเนา
Chris S

โปรดทราบว่าIEnumerableไม่ได้เป็นชุดที่สมบูรณ์ของ "อ่านเท่านั้น" Containsวิธีการเช่นมันไม่ได้มีวิธีการเช่น
jrh

8

ใน 2.0 คุณสามารถโทรAsReadOnlyเพื่อรับรายการเวอร์ชันอ่านอย่างเดียว หรือห่อสิ่งที่มีอยู่IListในReadOnlyCollection<T>วัตถุ


นั่นคือสิ่งที่เทียบเท่ากับ Collections.unmodifiablelist (รายการ) ฉันตามมา
Chris S

ฉันพลาดสิ่งนี้ใน. NET 4 เพราะฉันใช้ IList <T> แทนรายการจริง <T> ตรวจสอบให้แน่ใจว่า AsReadOnly ยังคงมีอยู่ใน. NET 4 ตราบเท่าที่คุณจัดการกับ aa List <T>
BlueMonkMN

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