2012-05-02 27 views
32

Tôi có câu hỏi về số đặt hàng trong IEnumerable (hoặc IEnumerable<T>, không quan trọng).IEnumerable and order

Như chúng ta đã biết, lặp qua IEnumerable là pseudo-code có thể được viết theo cách sau:

while (enumerable.HasNext()) 
{ 
    object obj = enumerable.Current; 
    ... 
} 

Bây giờ, giả sử, mà người ta cần để hoạt động trên một sắp xếp bộ sưu tập. IEnumerable có thể được sử dụng trong trường hợp này hay là tốt hơn để thử các phương tiện khác (tức là IList) với hỗ trợ chỉ mục?

Nói cách khác: hợp đồng của IEnumerable có thực hiện bất kỳ đảm bảo nào về đơn đặt hàng nói chung không?

UPD: Vì vậy, IEnumerable không phải là phương tiện thích hợp cho giao diện chung đảm bảo đặt hàng. Câu hỏi mới là giao diện hoặc lớp học nên nào được sử dụng cho một bộ sưu tập không thay đổi theo thứ tự? ReadonlyCollection? IList? Cả hai phương pháp này đều chứa phương thức Add() (thậm chí không được thực hiện trong phương thức cũ). Bất kỳ đề xuất nào?

P.S Suy nghĩ của riêng tôi: IEnumerable không cung cấp bất kỳ đảm bảo nào về yêu cầu đặt hàng. Việc triển khai chính xác có thể trả lại các phần tử giống nhau theo thứ tự khác nhau trong các bảng liệt kê khác nhau (xem xét truy vấn SQL)

P.P.S. Tôi biết về LINQ First(), nhưng nếu IEnumerable không nói một từ về thứ tự của nó, tiện ích mở rộng này hoàn toàn vô ích.

Trả lời

25

IEnumerable/IEnumerable<T> không đảm bảo về đặt hàng, nhưng việc triển khai sử dụng IEnumerable/IEnumerable<T> có thể hoặc không thể đảm bảo đặt hàng.

Ví dụ: nếu bạn liệt kê List<T>, đơn đặt hàng được đảm bảo, nhưng nếu bạn liệt kê HashSet<T> thì không đảm bảo được cung cấp, nhưng cả hai sẽ được liệt kê bằng giao diện IEnumerable<T>.

+1

Ví dụ khác là 'Dictionary <,>'. Nó được ghi rõ rằng thứ tự các mục của nó được liệt kê là không xác định. Vì vậy, mã như 'dict.Last(). Key' (trong đó' dict' là một 'Dictionary <,>' và 'Last()' là phương pháp mở rộng LINQ) không có ý nghĩa. (Tôi nghe nói về một nhà phát triển làm chính xác điều đó.) –

+1

Tôi đã thêm vào đã nói rằng điều quan trọng là phải hiểu chính xác những gì được đảm bảo về thứ tự cho một số bộ sưu tập chung chung. Vì vậy, bảo đảm đơn đặt hàng không phải là về một thứ tự cụ thể (như là kết quả của việc phân loại), nhưng về bảo đảm rằng thứ tự của các thành phần của cùng một bộ sưu tập là giống nhau cho các lần liệt kê tiếp theo. Hầu hết các bộ sưu tập không bảo đảm rõ ràng điều đó. IList chỉ thể hiện một loại từ điển trong đó các khóa là các chỉ mục. –

+0

IOrderedEnumerable có thể là dấu hiệu để tin rằng bộ sưu tập đảm bảo thứ tự (mặc dù giao diện vẫn không), nhưng nó nhiều hơn chúng ta cần - nó thường đại diện cho một thứ tự SORT cụ thể, trong khi chúng ta cần bất kỳ thứ tự (ngẫu nhiên) nào đảm bảo giữa các điều khoản. Để kết luận, chỉ việc triển khai cụ thể mới thực sự có thể đảm bảo thứ tự (ví dụ: Mảng, Danh sách ). –

12

Chi tiết triển khai. IEnumerable sẽ liệt kê các mục - cách thực hiện đó là tùy thuộc vào việc thực hiện. Danh sách MOST vv chạy theo thứ tự tự nhiên của chúng (chỉ số 0 trở lên, v.v.).

hợp đồng của IE có thể đảm bảo cho chúng tôi một số đơn đặt hàng trong trường hợp chung không?

Không, nó chỉ đảm bảo liệt kê (mỗi mục một lần, v.v.). IEnumerable không có thứ tự đảm bảo vì nó cũng có thể sử dụng được trên các mục không có thứ tự.

Tôi biết về LINQ First(), nhưng nếu IEnumerable không nói một từ về thứ tự của nó, phần mở rộng này là khá vô ích.

Không, không phải vì bạn có thể có thứ tự nội tại. Bạn cung cấp cho SQL làm ví dụ - kết quả là một IEnumerable, nhưng nếu tôi đã thực thi thứ tự trước (Bằng cách sử dụng OrderBy()) thì IEnumerable được sắp xếp theo định nghĩa của LINQ. AsEnumerable(). Đầu tiên() đưa tôi đến mục đầu tiên của Order.

4

Bạn kết hợp hai điểm: liệt kê và sắp xếp.

Khi bạn liệt kê trên IEnumerable, bạn không nên quan tâm đến đơn đặt hàng. Bạn làm việc với giao diện và việc triển khai nó sẽ quan tâm đến trật tự.

Ví dụ:

void Enumerate(IEnumerable sequence) 
{ 
    // loop 
} 

SortedList<T> sortedList = ... 
Enumerate (sortedList); 

Bên trong phương pháp nó vẫn còn một danh sách với trật tự cố định, nhưng phương pháp không biết về thực hiện giao diện cụ thể và đó là đặc thù.

6

Có lẽ bạn đang tìm kiếm giao diện IOrderedEnumerable? Nó được trả về bởi các phương thức mở rộng như OrderBy() và cho phép phân loại tiếp theo với ThenBy().

+0

Thật không may điều này sẽ không hoạt động nếu bạn muốn chấp nhận các giao diện như IList đảm bảo một đơn đặt hàng nhưng không được kế thừa từ IOrderedEnumerable. Xem http://stackoverflow.com/q/5429974/1157054 – Ajedi32