Czy powrót z bloku próbnego złapania w końcu jest złą praktyką?

128

Więc dziś rano natknąłem się na kod, który wyglądał tak:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Teraz ten kod kompiluje się dobrze i działa tak, jak powinien, ale po prostu nie wydaje się dobrze wracać z bloku try, zwłaszcza jeśli w końcu jest skojarzony.

Moim głównym problemem jest to, co się stanie, jeśli w końcu wyrzuci własny wyjątek? Masz zwróconą zmienną, ale także wyjątek, z którym musisz się uporać ... więc jestem zainteresowany, aby wiedzieć, co inni myślą o powrocie z bloku try?

lomaxx
źródło
13
Jedną z zalet tego stylu jest to, że nie musisz deklarować xpoza tryblokiem. Możesz zachować swoją deklarację blisko jej użycia.
David R Tribble

Odpowiedzi:

169

Nie, to nie jest zła praktyka. Umieszczenie returntam, gdzie ma to sens, poprawia czytelność i łatwość konserwacji oraz sprawia, że ​​kod jest łatwiejszy do zrozumienia. Nie należy się tym przejmować, ponieważ finallyblok zostanie wykonany, jeśli returnzostanie napotkana instrukcja.

Mehrdad Afshari
źródło
19

Ostatecznie zostanie wykonany bez względu na wszystko, więc to nie ma znaczenia.

Ed S.
źródło
9
Nie, w rzeczywistości nie chodzi tylko o podłączenie, istnieją pewne wyjątki zwane wyjątkami asynchronicznymi, takie jak StackOverflowException, ThreadAbortException i OutOfMemoryException, które mogą spowodować, że ostatni blok nie zostanie wykonany. Przeczytaj o ograniczonych regionach wykonywania do obsługi tych scenariuszy.
Mehrdad Afshari
14

Osobiście unikałbym tego rodzaju kodowania, ponieważ nie mam ochoty widzieć zwrotów przed ostatecznymi instrukcjami.

Mój umysł jest prosty i przetwarza rzeczy raczej liniowo. Dlatego, kiedy przejdę przez kod do pracy na sucho, będę miał tendencję do myślenia, że ​​kiedy dotrę do instrukcji return, wszystko, co następuje, nie ma znaczenia, co oczywiście jest w tym przypadku dość błędne (nie żeby wpłynęło to na instrukcję return, ale jakie mogą być skutki uboczne).

Tak więc ułożyłbym kod tak, aby instrukcja return zawsze pojawiała się po instrukcjach final.

Conrad
źródło
9

To może odpowiedzieć na twoje pytanie

Co naprawdę dzieje się podczas try {return x; } wreszcie {x = null; } oświadczenie?

Po przeczytaniu tego pytania wydaje się, że możesz mieć inną strukturę try catch w instrukcji final, jeśli myślisz, że może ona zgłosić wyjątek. Kompilator ustali, kiedy zwrócić wartość.

To powiedziawszy, może i tak lepiej byłoby zrestrukturyzować swój kod, aby nie zmylić ciebie później ani kogoś, kto może być tego nieświadomy.

Spencer Ruport
źródło
hmmm bardzo interesujące. Oznacza to, że jest to bezpieczne, ale czy to oznacza, że ​​należy tego unikać?
lomaxx
3
Osobiście uważam, że to sprawia, że ​​czytelność twojego kodu jest trochę trudna i samo to wystarczyłoby, abym wymyślił inny sposób strukturyzowania kodu. Ale tak naprawdę to tylko osobiste preferencje.
Spencer Ruport
3
Zwykle
Myślę, że zwrot jest w porządku, gdzie to jest. Metoda zwróci wartość, chyba że zostanie zgłoszony wyjątek; nie ma znaczenia, jeśli wyjątek wystąpi w kodzie ostatecznego oczyszczania.
Lawrence Dol
Zwróć uwagę, że ograniczenie powrotu z wreszcie nie jest obecne w Javie (ale myślę, że ograniczenie jest dobre - chwała dla C #).
Lawrence Dol
5

Funkcjonalnie nie ma różnicy.

Jest jednak jeden powód, aby tego nie robić. Dłuższe metody z kilkoma punktami wyjścia są często trudniejsze do odczytania i analizy. Ale ten sprzeciw ma więcej wspólnego z instrukcjami powrotu niż catch i ostatecznie blokami.

Ifeanyi Echeruo
źródło
Sprzeciwiłbym się
3

W twoim przykładzie oba sposoby są równoważne, nie zdziwiłbym się nawet, gdyby kompilator wygenerował ten sam kod. Jeśli wyjątek wystąpi w bloku final, masz te same problemy, niezależnie od tego, czy umieścisz instrukcję return w bloku, czy poza nim.

Prawdziwe pytanie brzmi: stylistycznie, który jest najlepszy. Lubię pisać moje metody tak, aby była tylko jedna instrukcja return, w ten sposób łatwiej jest zobaczyć przepływ z metody, wynika z tego, że lubię również umieszczać instrukcję return na końcu, więc łatwo jest zobaczyć, że tak jest koniec metody i to co zwraca.

Myślę, że przy tak starannie umieszczonej instrukcji return, jak ostatnia instrukcja, inne są mniej prawdopodobne, że pojawią się i wrzucą wiele instrukcji powrotu do innych części metody.

Być ostrzeżonym
źródło