Bảng liệt kê theo thứ tự: IEnumerable hoặc Array (bằng C #)?


8

Bối cảnh điển hình: Tôi tạo một phương thức mở rộng cho một bộ sưu tập xem xét các yếu tố được sắp xếp. Hàm bắt đầu từ đầu, ở chỉ số 0 và thứ tự có ý nghĩa. Ví dụ: Nhóm theo trình tự hoặc Chỉ mục của một mục .

Tuy nhiên, tôi luôn luôn bối rối không biết nên mở rộng điều gì: IEnumerable<T>hay T[]. Lý do của tôi là sự rõ ràng về mục đích: Một mảng có một khái niệm về thứ tự, trong khi một IEnumerable được thực hiện bởi nhiều bộ sưu tập chung, không phải tất cả đều có khái niệm về thứ tự:

  • Từ điển - không có thứ tự
  • Hashset - không có thứ tự
  • LinkedList - đã đặt hàng
  • Danh sách - đặt hàng
  • Xếp hàng - đặt hàng
  • SortedDixi - được sắp xếp (không phải thứ tự gốc)
  • SortedList - được sắp xếp (không phải thứ tự gốc)
  • Sắp xếp - sắp xếp (không phải thứ tự gốc)
  • Ngăn xếp - đảo ngược

Cũng như bất kỳ thực hiện nào khác có thể hoặc không thể được ra lệnh.

Ngoài ra, tôi không chắc chắn nếu điều tra viên được thiết lập lại nếu việc liệt kê chưa hoàn thành, vì vậy nếu đó là một điều đáng lo ngại, thì ai biết tại thời điểm nào việc liệt kê sẽ bắt đầu? Việc liệt kê một mảng sẽ luôn bắt đầu từ đầu.

Vì vậy, với tôi, nó có ý nghĩa hơn để mở rộng a T[]. Nhưng tôi có đúng trong suy nghĩ đó không? Tôi có lo lắng quá không? Cách tiếp cận phù hợp để đảm bảo liệt kê "ra lệnh" là gì?

Câu trả lời:


13

Tôi không chắc chắn nếu điều tra viên được thiết lập lại nếu việc liệt kê chưa hoàn thành, vì vậy nếu đó là một điều đáng lo ngại, thì ai biết tại thời điểm nào việc liệt kê sẽ bắt đầu? Việc liệt kê một mảng sẽ luôn bắt đầu từ đầu.

Hai câu này khiến tôi nghĩ rằng bạn có những hiểu lầm sâu sắc về cách thức hoạt động của mô hình vô số. Bạn có thể giải thích lý do tại sao bạn nghĩ rằng một điều tra viên bị bỏ rơi có bất cứ điều gì để làm với một bảng liệt kê sau này ?

Một liệt kê là một thiết bị tạo ra các điều tra viên . Nếu một điều tra viên bị bỏ rơi, điều đó không ảnh hưởng đến vô số. Nếu tôi bán sách và Bob mua một cuốn sách và chỉ đọc được nửa chừng, điều đó không có nghĩa là khi tôi bán một bản sao khác của cuốn sách cho Alice, cô ấy phải bắt đầu đọc nơi Bob rời đi.

Tôi luôn luôn bối rối không biết nên mở rộng điều gì: IEnumerable<T>hay T[]. Lý do của tôi là sự rõ ràng về mục đích: Một mảng có một khái niệm về thứ tự, trong khi một IEnumerable được thực hiện bởi nhiều bộ sưu tập chung, không phải tất cả đều có khái niệm về thứ tự:

Phương thức mở rộng của bạn có cần (1) truy cập vào bộ sưu tập không theo thứ tự không? (2) viết vào bộ sưu tập?

Nếu vậy, sau đó mở rộng IList<T>Nếu không, mở rộng IEnumerable<T>.

Điều gì về: (3) truyền bộ sưu tập vào một phương thức mong đợi một mảng?

Sau đó mở rộng mảng.

Câu hỏi của bạn về cơ bản là "Tôi không biết nên mở rộng Động vật hay Hươu cao cổ". Nếu phương pháp mở rộng của bạn không dành riêng cho Giraffes, hãy mở rộng Animal. Nếu phương pháp tiện ích mở rộng của bạn không dành riêng cho mảng, hãy mở rộng tất cả các danh sách. Nếu nó không cụ thể cho danh sách, mở rộng tất cả các chuỗi. Nếu nó không cụ thể cho các chuỗi, tỷ lệ cược là một phương pháp mở rộng là cơ chế sai cho bạn; Tôi đề nghị chống lại việc mở rộng tất cả các đối tượng.


Tôi có một sự thiếu hiểu biết lớn, đáng xấu hổ về cách thức hoạt động của mô hình vô số. Tôi đoán đó là lý do tại sao tôi ở đây hỏi điều này.
MPelletier

Chết tiệt, tôi đã hoàn toàn quên lớp cấu trúc dữ liệu của mình. Tất nhiên nó không ảnh hưởng đến việc liệt kê sau này! Tôi đã che đậy bản thân trong sự xấu hổ ... :(
MPelletier

@MPelletier: Câu hỏi của bạn vẫn giữ giá trị. Có an toàn không / có ý nghĩa gì khi chạy một thuật toán trong đó thứ tự có tầm quan trọng trên ví dụ a Dictionary? Chắc là không. Như Scott Meyers đã nói: "Cách tốt nhất để ngăn chặn việc sử dụng không chính xác là làm cho việc sử dụng đó là không thể." . Có thể / sẽ có ích khi làm như vậy trong kịch bản này?
Steven Jeuris

1
@EricLippert: 3 điểm bạn đề cập là lý do tại sao bạn phải mở rộng mảng. Câu hỏi thực sự là, như trong nhận xét trước đây của tôi, nó có đáng để ngăn chặn việc sử dụng không chính xác không? Hy vọng bạn có thể mở rộng một chút về điều đó ...
Steven Jeuris

@StevenJeuris Câu hỏi của bạn sẽ không cần thiết nếu C # được thiết kế đúng và có giao diện ISortCollection <T>, bạn sẽ mở rộng nếu bạn cần sắp xếp bộ sưu tập. Nhưng vì không, cách duy nhất để ngăn chặn việc sử dụng sai vào thời gian biên dịch là mở rộng một loại quá hẹp (IList <T>) hoặc mở rộng IEnumerable <T> và thực hiện một loại không cần thiết.
Jim Balter

2

Tôi nghĩ rằng bạn muốn kết hợp 2 khái niệm khác nhau thành 1. Cấu trúc dữ liệu và thứ tự nội dung của nó là 2 thứ riêng biệt.

Đặt hàng là một chủ đề khó khăn. Ví dụ, việc sắp xếp một danh sách những người có nghĩa là gì? Ngay cả khi khóa thứ tự / sắp xếp được xác định, nó phải có hướng và bạn phải quyết định phải làm gì với null (nếu có), các vấn đề về ngày, v.v.

Nếu thứ tự dữ liệu là quan trọng đối với phương thức của bạn, thì có thể phương thức của bạn phải chịu trách nhiệm cho việc sắp xếp dữ liệu như là một phần của thiết lập thay vì yêu cầu dữ liệu được người gọi yêu cầu. Một cách tiếp cận tương tự được sử dụng bởi một số thuật toán khớp chuỗi trong đó một từ điển được xây dựng bên trong phương thức tìm kiếm từ chuỗi đã truyền trước khi chuỗi được tìm kiếm. Tôi biết đây không phải là trường hợp chính xác, nhưng nó là ví dụ gần nhất tôi có thể nghĩ ra.


2
Một phương thức đặt hàng như một đối số ... Hmmm, thú vị!
MPelletier

Thậm chí sau đó, trật tự có thể được ẩn. Đó là vấn đề chính tôi đang gặp phải. Tôi hiểu rằng khái niệm về LINQ là mô phỏng các chức năng cơ sở dữ liệu và theo 1NF, các bản ghi không có thứ tự. Thật không may, thế giới thực hiếm khi là 1NF.
MPelletier

"Thế giới thực hiếm khi là 1NF", có đúng trong một số trường hợp, nhưng tôi không chắc điều đó sẽ ảnh hưởng đến trường hợp bạn mô tả ở đây như thế nào?
NoChance

1NF : "Không có thứ tự từ trên xuống dưới cho các hàng." Đó là những gì đang xảy ra ở đây, tôi nghĩ. Có thứ tự từ trên xuống dưới trong nhật ký, trong rất nhiều "bộ sưu tập" lỏng lẻo. LINQ được thiết kế để làm việc trên các bộ sưu tập như thể chúng là cơ sở dữ liệu, nhưng có thể có thứ tự từ trên xuống dưới, do đó mâu thuẫn tôi vừa thấy.
MPelletier

1

IEnumerable tuyên bố rằng bộ sưu tập bạn có thể được liệt kê; nó không ngụ ý bất cứ điều gì về nội dung. Đây không phải là một điều xấu - các container có thể có các khả năng và hạn chế bổ sung trên các giao diện riêng lẻ.

(Tôi không thấy một mảng nào tốt hơn ở đây - nó có thể lập chỉ mục, cũng như IList và các thùng chứa khác, nhưng không có gì về lập chỉ mục ngụ ý thứ tự dữ liệu. Danh sách của bạn là loại lẻ - một số mặt hàng được "đặt hàng "trong đó họ bảo toàn thứ tự chèn, những thứ khác được" sắp xếp "như trong chúng được sắp xếp. Chúng là hai thứ khác nhau. Khác với Sắp xếp / Sắp xếp / Sắp xếp / Từ điển, bạn không nên cho rằng dữ liệu theo thứ tự cụ thể trừ khi bạn xử lý việc đó bên trong mã của riêng bạn.)

Tuy nhiên, IEnumerable cung cấp tiện ích mở rộng LINQ cho phép bạn .OrderBy, vì vậy mọi thứ có thể đếm được đều có thể được trả về theo thứ tự được sắp xếp theo IOrderedEnumerable. Mặc dù đó là giao diện dành riêng cho LINQ (và không được triển khai theo mặc định bởi Sortedset / SortedList / SortedDipedia, do đó, có thể không có ý nghĩa gì khi mở rộng giao diện cụ thể đó ...)


2
Điều tôi muốn tránh là tạo ra một loạt các chức năng hoạt động "chỉ khi được đặt hàng", sau đó nhiều tháng, một người nào đó sử dụng thư viện trên một bộ sưu tập không có thứ tự và tự hỏi tại sao nó lại cho kết quả thú vị. Bên cạnh tài liệu tốt mà tất cả mọi người sẽ đọc kỹ, tất nhiên.
MPelletier

Và tôi không nghĩ việc mở rộng IOrderedEnumerable sẽ khiến tôi trở thành bất kỳ người hâm mộ nào. Một số danh sách đã được sắp xếp (ví dụ như tệp nhật ký được phân tích cú pháp. Thứ tự là số dòng, nhưng không có điểm nào để sắp xếp theo nó nếu nó được đọc tuần tự.
MPelletier

Ngày nay không có một trình trang trí / giao diện nào có thể cho bạn biết / cảnh báo người dùng rằng một bộ sưu tập được sắp xếp là cần thiết cho phương thức mở rộng của bạn. Đặc biệt đối với dữ liệu tùy ý, làm thế nào bạn biết (không có chức năng so sánh) liệu dữ liệu đã được đặt hàng hay chưa?
Joe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.