Gdy musisz powtórzyć czytnik, w którym liczba pozycji do odczytania jest nieznana, a jedynym sposobem jest kontynuowanie czytania, aż do końca.
Często jest to miejsce, w którym potrzebujesz niekończącej się pętli.
Zawsze jest to,
true
co oznacza, że gdzieś wewnątrz bloku musi być instrukcjabreak
lubreturn
int offset = 0; while(true) { Record r = Read(offset); if(r == null) { break; } // do work offset++; }
Istnieje metoda podwójnego odczytu dla pętli.
Record r = Read(0); for(int offset = 0; r != null; offset++) { r = Read(offset); if(r != null) { // do work } }
Jest jedna pętla odczytu podczas odczytu. Nie wszystkie języki obsługują tę metodę .
int offset = 0; Record r = null; while((r = Read(++offset)) != null) { // do work }
Zastanawiam się, które podejście jest najmniej prawdopodobne, aby wprowadzić błąd, najbardziej czytelny i powszechnie używany.
Za każdym razem, gdy muszę napisać jedną z nich, myślę „musi być lepszy sposób” .
c#
code-quality
readability
Reactgular
źródło
źródło
Odpowiedzi:
Cofnąłbym się tutaj. Koncentrujesz się na wybrednych szczegółach kodu, ale brakuje większego obrazu. Rzućmy okiem na jedną z twoich przykładowych pętli:
Jakie jest znaczenie tego kodu? Oznacza to: „popracuj nad każdym rekordem w pliku”. Ale nie tak wygląda kod . Kod wygląda jak „zachowaj przesunięcie. Otwórz plik. Wejdź w pętlę bez warunku zakończenia. Przeczytaj rekord. Testuj pod kątem nieważności”. Wszystko to zanim przejdziemy do pracy! Pytanie, które powinieneś zadać, brzmi: „w jaki sposób mogę dopasować wygląd tego kodu do semantyki? ” Ten kod powinien być:
Teraz kod brzmi jak jego intencja. Oddziel swoje mechanizmy od semantyki . W swoim oryginalnym kodzie łączysz mechanizm - szczegóły pętli - z semantyką - pracą wykonaną dla każdego rekordu.
Teraz musimy wdrożyć
RecordsFromFile()
. Jaki jest najlepszy sposób na wdrożenie tego? Kogo to obchodzi? To nie jest kod, na który ktoś będzie patrzył. Jest to podstawowy kod mechanizmu i jego dziesięć linii. Napisz, jak chcesz. Co powiesz na to?Teraz, gdy manipulujemy leniwie obliczoną sekwencją rekordów, możliwe są wszelkiego rodzaju scenariusze:
I tak dalej.
Za każdym razem, gdy piszesz pętlę, zadaj sobie pytanie: „czy ta pętla czyta się jak mechanizm czy jak znaczenie kodu?” Jeśli odpowiedź brzmi „jak mechanizm”, spróbuj przenieść ten mechanizm do własnej metody i napisz kod, aby znaczenie było bardziej widoczne.
źródło
Nie potrzebujesz niekończącej się pętli. Nigdy nie powinien być potrzebny w scenariuszach odczytu C #. To jest moje preferowane podejście, zakładając, że naprawdę musisz zachować przesunięcie:
Takie podejście potwierdza fakt, że istnieje etap konfiguracji czytnika, więc istnieją dwa wywołania metody odczytu.
while
Stan jest na początek pętli, tylko w przypadku braku danych w ogóle w czytniku.źródło
To zależy od twojej sytuacji. Ale jednym z bardziej „C # -ishowych” rozwiązań, które mogę wymyślić, jest użycie wbudowanego interfejsu IEnumerable i pętli foreach. Interfejs IEnumerator wywołuje tylko MoveNext z prawdą lub fałszem, więc rozmiar może być nieznany. Następnie logika zakończenia jest zapisywana raz - w module wyliczającym - i nie trzeba powtarzać w więcej niż jednym miejscu.
MSDN stanowi przykład IEnumerator <T> . Musisz także utworzyć IEnumerable <T>, aby zwrócić IEnumerator <T>.
źródło
Kiedy mam operacje inicjalizacji, warunku i przyrostu, lubię używać pętli dla języków takich jak C, C ++ i C #. Lubię to:
Lub jeśli uważasz, że jest to bardziej czytelne. Ja osobiście wolę ten pierwszy.
źródło