ใครสามารถอธิบายให้ฉันทำไมฉันต้องการใช้ IList มากกว่ารายชื่อใน C #?
คำถามที่เกี่ยวข้อง: เหตุใดจึงถือว่าไม่ดีที่จะเปิดเผยList<T>
ใครสามารถอธิบายให้ฉันทำไมฉันต้องการใช้ IList มากกว่ารายชื่อใน C #?
คำถามที่เกี่ยวข้อง: เหตุใดจึงถือว่าไม่ดีที่จะเปิดเผยList<T>
คำตอบ:
ถ้าคุณเปิดเผยคลาสของคุณผ่านไลบรารี่ที่คนอื่นจะใช้คุณจะต้องเปิดเผยผ่านอินเตอร์เฟซแทนการใช้งานที่เป็นรูปธรรม สิ่งนี้จะช่วยถ้าคุณตัดสินใจที่จะเปลี่ยนการใช้งานคลาสของคุณในภายหลังเพื่อใช้คลาสคอนกรีตที่แตกต่างกัน ในกรณีนี้ผู้ใช้ห้องสมุดของคุณไม่จำเป็นต้องอัปเดตโค้ดเนื่องจากอินเทอร์เฟซไม่เปลี่ยนแปลง
หากคุณเพียงแค่ใช้มันภายในคุณอาจไม่สนใจมากนักและการใช้List<T>
อาจจะไม่เป็นไร
คำตอบที่ได้รับความนิยมน้อยกว่าคือโปรแกรมเมอร์ชอบแกล้งซอฟต์แวร์ของพวกเขาจะถูกนำมาใช้ซ้ำทั่วโลกเมื่อ infact โครงการส่วนใหญ่จะได้รับการดูแลโดยคนจำนวนเล็กน้อยและเสียงที่เกี่ยวข้องกับอินเตอร์เฟสที่ดี ด้วยตัวคุณเอง
นักบินอวกาศสถาปัตยกรรม โอกาสที่คุณจะเคยเขียน IList ของคุณเองที่เพิ่มอะไรลงไปในสิ่งที่อยู่ในกรอบการทำงาน. NET นั้นห่างไกลมากจนมันหมองคล้ำทางทฤษฎีที่สงวนไว้สำหรับ
เห็นได้ชัดว่าถ้าคุณถูกถามซึ่งคุณใช้ในการสัมภาษณ์คุณพูดว่า IList ยิ้มและทั้งคู่ต่างก็ดีใจที่เห็นว่าตัวเองฉลาด หรือสำหรับ API สาธารณะ, IList หวังว่าคุณจะได้รับคะแนนของฉัน
IEnumerable<string>
ภายในฟังก์ชันที่ฉันอาจใช้List<string>
สำหรับที่เก็บข้อมูลสำรองภายในเพื่อสร้างคอลเลกชันของฉัน แต่ฉันต้องการให้ผู้โทรระบุเนื้อหาของมันเท่านั้นไม่ใช่เพิ่มหรือลบ การยอมรับอินเทอร์เฟซเป็นพารามิเตอร์สื่อสารข้อความที่คล้ายกัน "ฉันต้องการชุดของสตริงไม่ต้องกังวลว่าฉันจะไม่เปลี่ยน"
อินเทอร์เฟซคือสัญญา (หรือสัญญา)
มันเป็นเสมอกับสัญญา - ขนาดเล็กที่ดีกว่า
IList
สัญญาคือ สัญญาที่เล็กกว่าและดีกว่าที่นี่คืออะไร? นี่ไม่ใช่เหตุผล
List<T>
เนื่องจากAddRange
ไม่ได้กำหนดไว้ในส่วนต่อประสาน
IList<T>
ทำให้สัญญาไม่สามารถรักษาได้ ตัวอย่างเช่นมีAdd
วิธีที่เกินกว่าที่จะโยนได้หากIList<T>
เกิดขึ้นเป็นแบบอ่านอย่างเดียว List<T>
ในทางกลับกันเขียนได้เสมอและรักษาสัญญาไว้เสมอ นอกจากนี้ตั้งแต่ .NET 4.6 ขณะนี้เรามีIReadOnlyCollection<T>
และที่มักจะพอดีกับที่ดีกว่าIReadOnlyList<T>
IList<T>
และพวกเขาเป็นโควาเรียนท์ หลีกเลี่ยงIList<T>
!
IList<T>
กัน บางคนก็สามารถนำไปใช้IReadOnlyList<T>
และทำให้ทุกวิธีมีข้อยกเว้นเช่นกัน มันตรงกันข้ามกับการพิมพ์เป็ด - คุณเรียกมันว่าเป็ด แต่มันไม่สามารถต้มตุ๋นเหมือนอย่างใดอย่างหนึ่งได้ นั่นเป็นส่วนหนึ่งของสัญญาแม้ว่าคอมไพเลอร์จะไม่สามารถบังคับใช้ได้ ฉันยอมรับ 100% ว่าIReadOnlyList<T>
หรือIReadOnlyCollection<T>
ควรใช้เพื่อการเข้าถึงแบบอ่านอย่างเดียว
บางคนพูดว่า "ใช้IList<T>
แทนทุกครั้งList<T>
"
พวกเขาต้องการให้คุณสามารถเปลี่ยนลายเซ็นของคุณจากวิธีการที่จะvoid Foo(List<T> input)
void Foo(IList<T> input)
คนเหล่านี้ผิด
มันเหมาะสมยิ่งกว่านั้นอีก หากคุณกลับมาIList<T>
เป็นส่วนหนึ่งของส่วนต่อประสานสาธารณะที่ห้องสมุดของคุณคุณอาจทิ้งตัวเลือกที่น่าสนใจเพื่อสร้างรายการที่กำหนดเองในอนาคต คุณอาจไม่จำเป็นต้องใช้ตัวเลือกนั้น แต่เป็นข้อโต้แย้ง ฉันคิดว่ามันเป็นอาร์กิวเมนต์ทั้งหมดสำหรับการคืนค่าอินเทอร์เฟซแทนที่จะเป็นรูปธรรม เป็นมูลค่าการกล่าวขวัญ แต่ในกรณีนี้มันมีข้อบกพร่องร้ายแรง
ในฐานะที่เป็นโต้เถียงเล็กน้อยคุณอาจพบว่าผู้ที่โทรเข้ามาทุกคนต้องได้รับList<T>
และรหัสการโทรก็เกลื่อนไปด้วย.ToList()
แต่ที่สำคัญกว่านั้นคือถ้าคุณยอมรับ IList ว่าเป็นพารามิเตอร์คุณควรระวังให้ดีกว่าเพราะIList<T>
และList<T>
ไม่ทำตัวเหมือนกัน แม้จะมีความคล้ายคลึงกันในชื่อและแม้จะมีการแชร์อินเตอร์เฟซที่พวกเขาไม่ได้เปิดเผยเดียวกันสัญญา
สมมติว่าคุณมีวิธีนี้:
public Foo(List<int> a)
{
a.Add(someNumber);
}
เพื่อนร่วมงานที่เป็นประโยชน์ "refactors" IList<int>
วิธีการที่จะยอมรับ
ขณะนี้รหัสของคุณint[]
ใช้งานไม่ได้เนื่องจากใช้งานIList<int>
แต่มีขนาดคงที่ สัญญาสำหรับICollection<T>
(ฐานIList<T>
) ต้องใช้รหัสที่ใช้ตรวจสอบการIsReadOnly
ตั้งค่าสถานะก่อนพยายามเพิ่มหรือลบรายการออกจากคอลเลกชัน สัญญาสำหรับList<T>
ไม่
หลักการชดเชย Liskov (ประยุกต์) ระบุว่าประเภทที่ได้รับควรจะสามารถใช้แทนประเภทฐานโดยไม่มีเงื่อนไขเพิ่มเติมหรือ postconditions
มันให้ความรู้สึกเหมือนว่ามันทำลายหลักการแทนที่ Liskov
int[] array = new[] {1, 2, 3};
IList<int> ilist = array;
ilist.Add(4); // throws System.NotSupportedException
ilist.Insert(0, 0); // throws System.NotSupportedException
ilist.Remove(3); // throws System.NotSupportedException
ilist.RemoveAt(0); // throws System.NotSupportedException
แต่มันก็ไม่ได้ คำตอบนี้คือตัวอย่างที่ใช้ IList <T> / ICollection <T> ผิด หากคุณใช้ ICollection <T> คุณต้องตรวจสอบการตั้งค่าสถานะ IsReadOnly
if (!ilist.IsReadOnly)
{
ilist.Add(4);
ilist.Insert(0, 0);
ilist.Remove(3);
ilist.RemoveAt(0);
}
else
{
// what were you planning to do if you were given a read only list anyway?
}
หากมีคนส่ง Array หรือ List ให้คุณรหัสของคุณจะทำงานได้ดีถ้าคุณตรวจสอบการตั้งค่าสถานะทุกครั้งและมี fallback ... แต่จริงๆแล้ว; ใครทำอย่างนั้น? คุณไม่ทราบล่วงหน้าหากวิธีการของคุณต้องการรายชื่อที่สามารถรับสมาชิกเพิ่มเติมได้ คุณไม่ได้ระบุไว้ในลายเซ็นวิธี? ว่าสิ่งที่คุณกำลังจะทำอะไรถ้าคุณได้ผ่านการอ่านรายชื่อเฉพาะเช่นint[]
?
คุณสามารถใช้แทนList<T>
เป็นรหัสที่ใช้IList<T>
/ ได้อย่างถูกต้องICollection<T>
คุณไม่สามารถรับประกันได้ว่าคุณสามารถทดแทนIList<T>
/ เป็นรหัสที่ใช้ICollection<T>
List<T>
มีการอุทธรณ์ไปยังหลักการความรับผิดชอบเดี่ยว / หลักการแยกส่วนติดต่อในข้อโต้แย้งจำนวนมากที่ใช้ abstractions แทนที่จะเป็นรูปธรรม - ขึ้นอยู่กับส่วนต่อประสานที่แคบที่สุดเท่าที่จะเป็นไปได้ ในกรณีส่วนใหญ่หากคุณใช้List<T>
และคุณคิดว่าคุณสามารถใช้อินเทอร์เฟซที่แคบกว่าแทนได้ - ทำไมIEnumerable<T>
ล่ะ นี่มักจะเป็นแบบที่ดีกว่าถ้าคุณไม่จำเป็นต้องเพิ่มรายการ หากคุณต้องการเพิ่มลงในคอลเล็กชันให้ใช้ประเภทคอนกรีต, List<T>
.
สำหรับฉันIList<T>
(และICollection<T>
) เป็นส่วนที่แย่ที่สุดของ. NET Framework IsReadOnly
ละเมิดหลักการของความประหลาดใจน้อยที่สุด คลาสเช่นArray
ที่ไม่อนุญาตให้เพิ่มการแทรกหรือลบรายการไม่ควรใช้อินเทอร์เฟซด้วยวิธีการเพิ่มแทรกและเอาออก (โปรดดู/software/306105/implementing-an-interface-when-you-dont-need-one-of-the-properties )
เป็นIList<T>
แบบที่ดีสำหรับองค์กรของคุณ? ถ้าเพื่อนร่วมงานขอให้คุณเปลี่ยนลายเซ็นวิธีที่จะใช้IList<T>
แทนการถามพวกเขาว่าพวกเขาต้องการเพิ่มองค์ประกอบต่อไปยังList<T>
IList<T>
หากพวกเขาไม่ทราบเกี่ยวกับIsReadOnly
(และคนส่วนใหญ่ทำไม่ได้) IList<T>
แล้วไม่ได้ใช้ เคย
โปรดทราบว่าการตั้งค่าสถานะ IsReadOnly มาจาก ICollection <T> และระบุว่ารายการสามารถเพิ่มหรือลบออกจากคอลเลกชัน; แต่เพียงเพื่อสร้างความสับสนให้กับสิ่งต่าง ๆ จริง ๆ มันไม่ได้ระบุว่าสามารถแทนที่ได้หรือไม่ซึ่งในกรณีของอาร์เรย์ (ซึ่งคืน IsReadOnlys == จริง) สามารถ
ดูข้อมูลเพิ่มเติมเกี่ยวกับ IsReadOnly ได้ที่คำจำกัดความ msdn ของ ICollection <T> IsReadOnly
IsReadOnly
จะtrue
เป็นIList
คุณก็ยังสามารถแก้ไขสมาชิกปัจจุบันได้! บางทีคุณสมบัตินั้นควรตั้งชื่อIsFixedSize
?
Array
เป็นIList
เพื่อที่ว่าทำไมฉันสามารถปรับเปลี่ยนสมาชิกในปัจจุบัน)
IReadOnlyCollection<T>
และIReadOnlyList<T>
ที่เกือบจะดีกว่าเสมอพอดีกว่าแต่ไม่ได้มีความหมายที่เป็นอันตรายของขี้เกียจIList<T>
IEnumerable<T>
และพวกเขาเป็นโควาเรียนท์ หลีกเลี่ยงIList<T>
!
List<T>
เป็นการใช้งานเฉพาะของIList<T>
ซึ่งเป็นภาชนะที่สามารถแก้ไขได้เช่นเดียวกับอาร์เรย์เชิงเส้นT[]
โดยใช้ดัชนีจำนวนเต็ม เมื่อคุณระบุIList<T>
เป็นประเภทของอาร์กิวเมนต์ของเมธอดคุณจะระบุว่าคุณต้องการความสามารถบางอย่างของคอนเทนเนอร์เท่านั้น
ตัวอย่างเช่นข้อกำหนดคุณสมบัติของอินเตอร์เฟสไม่บังคับใช้โครงสร้างข้อมูลเฉพาะที่จะใช้ การใช้งานList<T>
เกิดขึ้นกับประสิทธิภาพเดียวกันสำหรับการเข้าถึงการลบและการเพิ่มองค์ประกอบเป็นอาร์เรย์เชิงเส้น อย่างไรก็ตามคุณสามารถจินตนาการถึงการนำไปปฏิบัติที่ได้รับการสนับสนุนโดยรายการที่เชื่อมโยงแทนซึ่งการเพิ่มองค์ประกอบไปยังจุดสิ้นสุดนั้นถูกกว่า (เวลาคงที่) แต่การเข้าถึงแบบสุ่มมีราคาแพงกว่ามาก (โปรดทราบว่า. NET LinkedList<T>
ไม่ได้ใช้งานIList<T>
)
ตัวอย่างนี้ยังบอกคุณว่าอาจมีสถานการณ์เมื่อคุณต้องการระบุการนำไปปฏิบัติไม่ใช่อินเตอร์เฟสในรายการอาร์กิวเมนต์: ในตัวอย่างนี้เมื่อใดก็ตามที่คุณต้องการคุณสมบัติการเข้าถึงที่เฉพาะเจาะจง โดยปกติจะรับประกันการใช้งานเฉพาะของคอนเทนเนอร์ ( List<T>
เอกสารประกอบ: "ใช้IList<T>
อินเทอร์เฟซทั่วไปโดยใช้อาร์เรย์ที่มีขนาดเพิ่มขึ้นแบบไดนามิกตามต้องการ")
นอกจากนี้คุณอาจต้องการพิจารณาการเปิดเผยฟังก์ชั่นที่น้อยที่สุดที่คุณต้องการ ตัวอย่างเช่น. หากคุณไม่จำเป็นต้องเปลี่ยนเนื้อหาของรายการคุณควรพิจารณาใช้IEnumerable<T>
ซึ่งIList<T>
ขยายออกไป
LinkedList<T>
เทียบกับการList<T>
เทียบIList<T>
ทุกสื่อสารอะไรบางอย่างของการค้ำประกันผลการดำเนินงานที่จำเป็นโดยรหัสที่ถูกเรียกว่า
ฉันจะเปลี่ยนคำถามไปสักเล็กน้อยแทนที่จะให้เหตุผลว่าทำไมคุณควรใช้อินเทอร์เฟซเหนือการใช้งานที่เป็นรูปธรรมพยายามหาเหตุผลว่าทำไมคุณถึงต้องใช้การติดตั้งที่เป็นรูปธรรมแทนที่จะใช้อินเทอร์เฟซ หากคุณไม่สามารถปรับให้ใช้อินเทอร์เฟซ
IList <T> เป็นอินเทอร์เฟซเพื่อให้คุณสามารถสืบทอดคลาสอื่นและยังคงใช้ IList <T> ในขณะที่สืบทอดรายการ <T> ป้องกันไม่ให้คุณทำเช่นนั้น
ตัวอย่างเช่นหากมีคลาส A และคลาส B ของคุณสืบทอดมาคุณจะไม่สามารถใช้รายการ <T>
class A : B, IList<T> { ... }
หลักการของ TDD และ OOP โดยทั่วไปคือการเขียนโปรแกรมไปยังส่วนต่อประสานที่ไม่ใช่การใช้งาน
ในกรณีเฉพาะนี้เนื่องจากคุณกำลังพูดถึงโครงสร้างภาษาไม่ใช่แบบกำหนดเองที่โดยทั่วไปจะไม่สำคัญ แต่พูดเช่นที่คุณพบว่ารายการไม่รองรับสิ่งที่คุณต้องการ หากคุณเคยใช้ IList ในส่วนที่เหลือของแอพคุณสามารถขยายรายการด้วยคลาสที่กำหนดเองของคุณและยังสามารถส่งผ่านสิ่งนั้นได้โดยไม่ต้องทำการปรับปรุงใหม่
ค่าใช้จ่ายในการทำเช่นนี้มีน้อยมากทำไมไม่ช่วยให้คุณปวดหัวในภายหลัง นี่คือสิ่งที่หลักการอินเทอร์เฟซเกี่ยวกับ
public void Foo(IList<Bar> list)
{
// Do Something with the list here.
}
ในกรณีนี้คุณสามารถผ่านคลาสใดก็ได้ที่ใช้อินเทอร์เฟซ IList <Bar> หากคุณใช้ List <Bar> แทนจะสามารถส่งผ่านอินสแตนซ์ List <Bar> ได้เท่านั้น
วิธี IList <Bar> มีการรวมกันอย่างหลวม ๆ มากกว่าทาง List <Bar>
สมมติว่าไม่มีรายการคำถามใด ๆ เทียบกับ IList (หรือคำตอบ) กล่าวถึงความแตกต่างของลายเซ็น (ซึ่งเป็นสาเหตุที่ฉันค้นหาคำถามนี้ใน SO!)
ดังนั้นนี่คือวิธีการที่มีอยู่ในรายการที่ไม่พบใน IList อย่างน้อยที่สุดเท่ากับ. NET 4.5 (ประมาณปี 2015)
Reverse
และToArray
เป็นวิธีการขยายสำหรับ IEnumerable <T> interface ซึ่ง IList <T> มาจาก
List
การใช้งานIList
เท่านั้น
กรณีที่สำคัญที่สุดสำหรับการใช้อินเทอร์เฟซมากกว่าการใช้งานอยู่ในพารามิเตอร์ของ API ของคุณ หาก API ของคุณใช้พารามิเตอร์รายการทุกคนที่ใช้จะต้องใช้รายการ หากประเภทพารามิเตอร์คือ IList ผู้โทรจะมีอิสระมากขึ้นและสามารถใช้คลาสที่คุณไม่เคยได้ยินมาก่อนซึ่งอาจไม่มีอยู่จริงเมื่อโค้ดของคุณถูกเขียน
เกิดอะไรขึ้นถ้า .NET 5.0 แทนที่ไปSystem.Collections.Generic.List<T>
System.Collection.Generics.LinearList<T>
.NET มักจะเป็นเจ้าของชื่อList<T>
แต่พวกเขารับประกันว่าIList<T>
เป็นสัญญา ดังนั้น IMHO เรา (atleast I) จึงไม่ควรใช้ชื่อของใครบางคน (แม้ว่าจะเป็น. NET ในกรณีนี้) และประสบปัญหาในภายหลัง
ในกรณีที่ใช้IList<T>
งานผู้โทรจะต้องรับประกันสิ่งที่ต้องทำอยู่เสมอและผู้ดำเนินการมีอิสระที่จะเปลี่ยนการรวบรวมข้อมูลพื้นฐานให้เป็นการดำเนินการทางเลือกที่เป็นรูปธรรมของIList
แนวคิดทั้งหมดมีการระบุไว้โดยทั่วไปในคำตอบส่วนใหญ่เกี่ยวกับสาเหตุที่ใช้อินเทอร์เฟซเหนือการใช้งานที่เป็นรูปธรรม
IList<T> defines those methods (not including extension methods)
IList<T>
ลิงก์ MSDN
List<T>
ใช้วิธีการทั้งเก้า (ไม่รวมถึงวิธีการขยาย) นอกเหนือจากนั้นมีวิธีการสาธารณะประมาณ 41 วิธีซึ่งมีน้ำหนักในการพิจารณาว่าจะใช้วิธีใดในใบสมัครของคุณ
List<T>
ลิงก์ MSDN
คุณจะเนื่องจากการกำหนด IList หรือ ICollection จะเปิดขึ้นสำหรับการใช้งานอื่น ๆ ของอินเทอร์เฟซของคุณ
คุณอาจต้องการที่จะมี IOrderRepository ที่กำหนดชุดคำสั่งใน IList หรือ ICollection จากนั้นคุณสามารถมีการนำไปใช้งานหลายรูปแบบเพื่อจัดทำรายการคำสั่งซื้อตราบใดที่พวกเขาปฏิบัติตาม "กฎ" ที่กำหนดโดย IList หรือ ICollection ของคุณ
IList <> เป็นที่นิยมมากกว่าตามคำแนะนำของผู้โพสต์คนอื่น ๆ อย่างไรก็ตามทราบว่ามีข้อผิดพลาดใน. NET 3.5 sp 1เมื่อเรียกใช้ IList <> ผ่านมากกว่าหนึ่งรอบของอนุกรม / deserialization กับ WCF DataContractSerializer
ขณะนี้มี SP เพื่อแก้ไขข้อบกพร่องนี้: KB 971030
อินเตอร์เฟซให้แน่ใจว่าคุณอย่างน้อยได้รับวิธีการที่คุณจะคาดหวังว่า ; ตระหนักถึงความหมายของอินเทอร์เฟซเช่น วิธีนามธรรมทั้งหมดที่จะมีการดำเนินการโดยชั้นใดสืบทอดอินเตอร์เฟซ ดังนั้นหากบางคนทำคลาสใหญ่ของเขาเองด้วยวิธีการหลายอย่างนอกเหนือจากวิธีที่เขาได้รับมาจากอินเทอร์เฟซสำหรับฟังก์ชั่นเพิ่มเติมบางอย่างและสิ่งเหล่านั้นไม่เป็นประโยชน์กับคุณมันดีกว่าที่จะใช้การอ้างอิงถึงคลาสย่อย อินเตอร์เฟซ) และกำหนดวัตถุคลาสคอนกรีตให้มัน
ข้อได้เปรียบเพิ่มเติมคือรหัสของคุณปลอดภัยจากการเปลี่ยนแปลงใด ๆ ในระดับที่เป็นรูปธรรมในขณะที่คุณสมัครสมาชิกเพียงไม่กี่วิธีในการเรียนระดับคอนกรีตและสิ่งเหล่านั้นจะเป็นสิ่งที่จะมีตราบใดที่ระดับคอนกรีตสืบทอดจากอินเทอร์เฟซที่คุณเป็น การใช้ ดังนั้นความปลอดภัยสำหรับคุณและเป็นอิสระต่อผู้เขียนโปรแกรมที่กำลังเขียนการนำไปปฏิบัติอย่างเป็นรูปธรรมเพื่อเปลี่ยนหรือเพิ่มฟังก์ชันการทำงานให้กับชั้นเรียนที่เป็นรูปธรรมของเขา
คุณสามารถดูอาร์กิวเมนต์นี้จากหลาย ๆ มุมรวมถึงหนึ่งในวิธีการ OO ล้วนๆซึ่งบอกว่าจะตั้งโปรแกรมกับส่วนต่อประสานไม่ใช่การใช้งาน ด้วยความคิดนี้การใช้ IList ทำตามหลักการเดียวกันกับการผ่านไปและการใช้อินเทอร์เฟซที่คุณกำหนดตั้งแต่เริ่มต้น ฉันเชื่อในความสามารถในการปรับขนาดและความยืดหยุ่นที่ได้รับจากอินเทอร์เฟซทั่วไป หากจำเป็นต้องขยายหรือเปลี่ยนแปลงคลาส ILM <T> ที่เกี่ยวข้อง implant รหัสการบริโภคไม่จำเป็นต้องเปลี่ยน รู้ว่าสัญญาส่วนต่อประสาน IList เป็นอย่างไร อย่างไรก็ตามการใช้การนำไปปฏิบัติที่เป็นรูปธรรมและ List <T> ในชั้นเรียนที่มีการเปลี่ยนแปลงอาจทำให้ต้องมีการเปลี่ยนรหัสการโทรเช่นกัน นี่เป็นเพราะคลาสที่ปฏิบัติตาม IList <T> รับประกันพฤติกรรมบางอย่างที่ไม่ได้รับการรับรองโดยประเภทที่เป็นรูปธรรมโดยใช้รายการ <T>
นอกจากนี้ยังมีอำนาจที่จะทำสิ่งที่ต้องการปรับเปลี่ยนการดำเนินงานที่เริ่มต้นของรายการ <T> ในระดับการใช้ <T> IList สำหรับพูด .Add, .Remove หรือวิธี IList อื่น ๆ จะช่วยให้นักพัฒนาจำนวนมากของความยืดหยุ่นและอำนาจที่กำหนดไว้ล่วงหน้าเป็นอย่างอื่น ตามรายการ <T>
โดยทั่วไปวิธีการที่ดีคือการใช้ IList ใน API สาธารณะของคุณ (เมื่อเหมาะสมและจำเป็นต้องมีความหมายของรายการ) จากนั้นทำรายการภายในเพื่อใช้ API สิ่งนี้ช่วยให้คุณสามารถเปลี่ยนไปใช้ IList แบบอื่นโดยไม่ต้องใช้รหัสที่ใช้คลาสของคุณ
รายการชื่อชั้นอาจมีการเปลี่ยนแปลงในกรอบสุทธิ. ถัดไป แต่อินเทอร์เฟซจะไม่เปลี่ยนแปลงเนื่องจากอินเทอร์เฟซเป็นสัญญา
โปรดทราบว่าหาก API ของคุณจะถูกใช้เฉพาะในลูป foreach เป็นต้นคุณอาจต้องการพิจารณาเพียงแค่เปิดเผย IEnumerable แทน