Tôi nghĩ rằng một lợi thế của MoveNext()
mô hình C # /. NET so với hasNext()
mô hình của Java là trước đây ngụ ý rằng một số công việc có thể được thực hiện. Các hasNext()
phương pháp ngụ ý một kiểm tra trạng thái đơn giản. Nhưng điều gì sẽ xảy ra nếu bạn đang lặp lại một luồng lười biếng và bạn phải đi ra ngoài cơ sở dữ liệu để xác định xem có kết quả nào không? Trong trường hợp đó, cuộc gọi đầu tiên hasNext()
có thể là một hoạt động chặn dài. Việc đặt tên của hasNext()
phương thức có thể rất sai lệch như những gì đang thực sự xảy ra.
Đối với một ví dụ trong thế giới thực, vấn đề thiết kế này làm tôi khó chịu khi triển khai các API mở rộng phản ứng (Rx) của Microsoft trong Java. Cụ thể, đối với iterator được tạo bởi IObservable.asIterable()
để hoạt động đúng, hasNext()
phương thức sẽ phải chặn và chờ thông báo mục / lỗi / hoàn thành tiếp theo đến. Điều đó hầu như không trực quan: tên ngụ ý kiểm tra trạng thái đơn giản. Trái ngược với thiết kế C #, nơi MoveNext()
sẽ phải chặn, đây không phải là kết quả bất ngờ hoàn toàn khi bạn đang xử lý một luồng được đánh giá lười biếng.
Quan điểm của tôi là thế này: mô hình "next-iterator" thích hợp hơn mô hình "this-iterator" bởi vì mô hình "this-iterator" thường là một lời nói dối: bạn có thể được yêu cầu tìm nạp trước phần tử tiếp theo để kiểm tra trạng thái của vòng lặp. Theo tôi, một thiết kế truyền đạt khả năng đó rõ ràng là tốt hơn. Đúng, các quy ước đặt tên của Java thực hiện theo mô hình "tiếp theo", nhưng các hàm ý hành vi tương tự như các mô hình "mô hình lặp này".
Làm rõ: Có lẽ tương phản Java và C # là một lựa chọn kém, bởi vì mô hình của Java là lừa đảo. Tôi coi sự khác biệt quan trọng nhất trong các mô hình được OP trình bày là mô hình "trình lặp này" tách rời logic "hợp lệ" từ logic "truy xuất phần tử hiện tại / tiếp theo", trong khi triển khai "trình lặp tiếp theo" lý tưởng kết hợp các hoạt động này. Tôi cảm thấy thích hợp để kết hợp chúng bởi vì, trong một số trường hợp, việc xác định xem trạng thái của trình lặp có hợp lệ hay không đòi hỏi phải tìm nạp trước phần tử tiếp theo , do đó khả năng đó phải được làm rõ ràng nhất có thể.
Tôi không thấy sự khác biệt đáng kể về thiết kế giữa:
while (i.isValid()) { // do we have an element? (implied as fast, non-blocking)
doSomething(i.current()); // retrieve the element (may be slow!)
i.next();
}
// ...and:
while (i.hasNext()) { // do we have an element? (implied as fast, non-blocking)
doSomething(i.next()); // retrieve the element (may be slow!)
}
Nhưng tôi thấy một sự khác biệt có ý nghĩa ở đây:
while (i.hasNext()) { // do we have an element? (implied as fast, non-blocking)
doSomething(i.next()); // retrieve the element (may be slow!)
}
// ...and:
while (i.moveNext()) { // fetch the next element if it exists (may be slow!)
doSomething(i.current()); // get the element (implied as fast, non-blocking)
}
Trong cả isValid()
và hasNext()
ví dụ, hoạt động được ngụ ý là kiểm tra trạng thái nhanh và không chặn trên thực tế có thể là hoạt động chặn chậm . Trong moveNext()
ví dụ này, hầu hết các công việc đang được thực hiện theo phương pháp bạn mong đợi, bất kể bạn đang xử lý một luồng được đánh giá háo hức hay lười biếng.