Để sử dụng chức năng tuyệt vời như ConvertAll()
, tôi phải chuyển đổi IList
thành List
, thật là đau đớn.Tại sao IList <> có ít tính năng hơn Danh sách <>?
Trả lời
Lưu ý rằng List<>
là triển khai IList<>
với bộ nhớ thực, nghĩa là nó giữ một mảng ở chế độ nền. Nói chung, một IList<>
có thể là một proxy cho một cái gì đó khác. Trong db4o và linq để sql, IList<>
của bạn có thể 'trỏ tới truy vấn', tức là truy cập vào danh sách sẽ kích hoạt một hoạt động cơ sở dữ liệu.
Bằng cách này, bạn có thể thực hiện myList.Skip(600).Take(20);
để thực hiện phân trang và chỉ trong bước này truy vấn thực tế sẽ được thực thi. Một List<>
chứa một triệu mục sẽ rất lớn, trong khi có thể có IList<>
s có số lượng lớn Count
, nhưng không ăn một lượng bộ nhớ đáng kể - miễn là bạn không truy cập vào các phần tử.
ConvertAll
sẽ yêu cầu mọi đối tượng được khởi tạo để nó hoạt động tốn kém. Vì vậy, nó là tốt hơn để làm cho hoạt động rõ ràng và buộc bạn phải lấy một thực hiện cụ thể của giao diện. Rõ ràng, chuyển đổi đòi hỏi tất cả các đối tượng được khởi tạo anyway, do đó, không có lợi ích trong việc làm nó lười biếng.
Vì giao diện xác định một hành vi duy nhất, trong khi một lớp có thể triển khai một số giao diện khác nhau và cũng có các tính năng không được chỉ định bởi giao diện.
Nếu bạn muốn có khả năng của lớp List<T>
, không sử dụng tham chiếu IList<T>
. Sử dụng tham chiếu List<T>
ngay từ đầu.
Tại sao không sử dụng IEnumerable<T>.Select
thay vì List<T>.ConvertAll
? Kể từ khi IList
kế thừa IEnumerable
. Xem số này question trên SO.
Giao diện IList
được thiết kế để được triển khai rộng và rộng. Bằng cách bỏ qua các phương thức tiện lợi, điều đó có nghĩa là ít công việc hơn để thực hiện giao diện và ít cơ hội hơn để viết các lỗi.
May mắn thay, LINQ đã thực hiện bước này và thêm một loạt các phương thức hữu ích thông qua tính năng "phương pháp mở rộng". Select
và Cast
đặc biệt hữu ích cho mục đích chuyển đổi. Đảm bảo rằng bạn nhắm mục tiêu Khuôn khổ .NET 3.5, tham chiếu đến cụm System.Core
và có using System.Linq;
để xem.
Đơn giản chỉ vì IList(T)
là một giao diện, trong khi List(T)
là một trong nhiều lớp trong bnet .net thực hiện IList(T)
với mục đích có chức năng chỉ mục. Không phải tất cả các lớp thực hiện IList(T)
sẽ yêu cầu phương thức ConvertAll()
, được sử dụng để chuyển đổi danh sách chung của một loại chung nhất định thành loại khác.
Mọi định nghĩa phương pháp hoặc thuộc tính trong một giao diện đều buộc phải thực hiện mọi giao diện để cung cấp mã cho giao diện đó. Nếu một giao diện được thực hiện bởi mười nghìn lớp trên toàn thế giới, thêm vào giao diện, một phương thức sẽ chỉ lấy một dòng mã thực thi để tăng thêm ít nhất bốn mươi nghìn dòng tổng số mã cần thiết cho tất cả các triển khai đó (giả sử trắng bình thường) -quy ước định vị). Ngược lại, việc thêm một phương thức trợ giúp vào một lớp không áp đặt các yêu cầu trên các giao diện thực hiện nó.
Ngẫu nhiên, một trong những mục danh sách mong muốn chính của tôi cho .net sẽ là phương tiện mà giao diện có thể tuyên bố thành viên là có triển khai mặc định thông qua phương pháp tĩnh (ví dụ:IFoo
bao gồm thành viên string Boz(int param)
có thể chỉ định rằng nếu mã cho một lớp tìm cách triển khai IFoo
không bao gồm thành viên đó, trình biên dịch hoặc thời gian chạy nên tự động tạo phương thức string IFoo.Boz(int param) { return IFoo_Helpers.Boz(this, param);}
. Đã có một phương thức như vậy tồn tại trong .net từ phiên bản 2.0, nó có thể có thể tiết kiệm hàng trăm ngàn, nếu không phải là hàng triệu, dòng mã ngay bây giờ, chỉ bằng cách có IEnumerable<T>
bao gồm việc thực hiện mặc định IEnumerator IEnumerable.GetEnumerator() {return IEnumerable_Helpers<T>.GetEnumerator(this);}
, với phương thức thứ hai đơn giản là static IEnumerable GetEnumerator(IEnumerable<T> it) {return it.GetEnumerator();}
. Một tính năng như vậy sẽ cho phép các giao diện cung cấp nhiều tính năng hơn cho người tiêu dùng của họ mà không áp đặt thêm bất kỳ công việc nào trên người thực hiện của họ. Hơn nữa, không giống như các phương thức mở rộng phải được ràng buộc tĩnh tại vị trí cuộc gọi, các phương thức giao diện như vậy sẽ bị ràng buộc khi thực hiện, do đó cho phép ghi đè cụ thể để sử dụng khi thích hợp (ví dụ, nếu IEnumerable<T>
cung cấp phương thức ToList
, List<T>
có thể xác định triển khai nhanh tạo ra List<T>
mới được khởi tạo trước với kích thước phù hợp và sử dụng Array.Copy
để điền vào và triển khai IEnumerable<T>
, sẽ trả về chuỗi vô tận có thể ném ngoại lệ (thay vì sử dụng hết bộ nhớ mà chúng có thể nhận), nhưng hầu hết các triển khai sẽ không phải làm bất cứ điều gì với phương pháp đó - chúng có thể đơn giản trì hoãn chức năng trợ giúp mục đích chung mặc định sẽ liệt kê các mục này thành một List<T>
mới và để cho nó phát triển khi cần.
- 1. Tại sao IList <>. Reverse() không hoạt động như Danh sách <>(). Đảo ngược
- 2. IList <Type> để IList <BaseType>
- 3. Tại sao IList <T> không có phương thức Chèn lấy IEnumerable <T>?
- 4. Tại sao Danh sách <T> triển khai IList <T>, ICollection <T> và IEnumerable <T>?
- 5. IEnumerable <T> VS IList <T> VS IQueryable <T>
- 6. Tại sao có Danh sách <T> .BinarySearch (...)?
- 7. Xóa các mục trong một IList <> từ một IList khác <>
- 8. IList <T> .FindIndex (Int32, Predicate <T>)
- 9. Làm cách nào tôi có thể khởi tạo một <IList <string>> IList?
- 10. Tại sao <chậm hơn> =
- 11. Không thể chuyển đổi Danh sách <KeyValuePair <...,...>> thành IEnumerable <object>?
- 12. C# Danh sách chuyển đổi <int> thành Danh sách <double>
- 13. DataTable vào Danh sách <object>
- 14. Tại sao Danh sách <Number> không phải là loại phụ của Danh sách <Object>?
- 15. Tại sao không có Sắp xếp cho IList <T>?!?! (đã chỉnh sửa)
- 16. Đúc Danh sách <x> vào danh sách <y>
- 17. Chuyển đổi Danh sách <MyObject> thành Từ điển <obj.string, Danh sách <obj.ID>>
- 18. Sao chép một danh sách <BaseClass> List <DerivedClass>
- 19. Danh sách chuyển đổi <Integer> thành Danh sách <String>
- 20. Tại sao mảng <T, N> lại chậm hơn vector <T>?
- 21. Danh sách <Object> vs Danh sách <dynamic>
- 22. Danh sách Hiệu suất SqlDataReader <string[]> hoặc Danh sách <object[]>
- 23. Bộ sưu tập <T> có bao gồm IList <T> hoặc liệt kê trên IList <T> không?
- 24. Danh sách định nghĩa <dl> yêu cầu mỗi <dd> sẽ có thẻ <dt> không?
- 25. Làm thế nào để có được IEnumerable <T> từ Danh sách <T>?
- 26. Nhập danh sách được phổ biến <BaseClass> vào Danh sách <ChildClass>
- 27. C# vấn đề sai: Gán Danh sách <Derived> như Danh sách <Base>
- 28. Cách thêm Danh sách <> vào Danh sách <> trong asp.net
- 29. Danh sách <?> so với Danh sách <? extends Object>
- 30. Chuyển đổi Danh sách <Enum> vào danh sách <string>
vui mừng khi biết về trường hợp db4o, tôi đang sử dụng nó ngay bây giờ. đối với trường hợp db4o, tôi không nên đóng db trước khi sử dụng IList <> phải không? – Benny
Đúng vậy, bạn sẽ kết thúc bằng 'DatabaseClosedException'. – mnemosyn
Bỏ qua và lấy là các phương thức IEnumerable <>, không nhất thiết phải là IList <>. – Dykam