2010-03-13 36 views

Trả lời

17

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.

+0

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

+0

Đúng vậy, bạn sẽ kết thúc bằng 'DatabaseClosedException'. – mnemosyn

+1

Bỏ qua và lấy là các phương thức IEnumerable <>, không nhất thiết phải là IList <>. – Dykam

4

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.

11

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.

1

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". SelectCast đặ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.

2

Đơ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.

0

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.

Các vấn đề liên quan