Jak poprawnie używać try, catchów

Jak poprawnie używać try, catchów
Kordoba
  • Rejestracja:około 5 lat
  • Ostatnio:około 24 godziny
  • Postów:151
0

Witam, jak poprawnie używać try catchów?
Zastanawiam się kiedy blok kodu otaczać try'em? Przecież tak naprawdę każda instrukcja może wyrzucić wyjątek? Choćby wyjście poza zakres tablicy. W takim wypadku można powiedzieć że cały program powinien być try'u. Może należy brać takie instrukcje które wyrzucają wyjątek nie z błędu programisty? Jak otwarcie FileStream (gdyż plik może nie istnieć), czy połączenie z bazą danych
(brak internetu). Prosiłbym o wytłumaczenie tego zagadnienia.

AK
  • Rejestracja:prawie 7 lat
  • Ostatnio:około miesiąc
  • Postów:3561
1

Ja bym zmienił patrzenie, nie "kiedy używać try", a "kiedy łapać catch". Zmiana czysto słowna, ale ważna

Łapać tam, gdzie jest z tego jakiś sens, gdzie da się coś mądrego z tym zrobić.
Inaczej mówiąc, w wielu miejscach nawet jak złapiemy wyjątek, niewiele z tym problemem zrobimy. Np funkcji obliczającej na tablicy przykładowe wyjście poza. Funkcja i tam musi wykonać return. Ale w punkcie wywołania BYĆ MOŻE tak.
Albo otwarcie połączenia do bazy w programie GUI. Samo w sobie jest nieudane, ale łapiąc w dobrym miejscu możemy usera poprosić o poprawienie parametrów.


Bo C to najlepszy język, każdy uczeń ci to powie
mad_penguin
mad_penguin
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 3 lata
  • Lokalizacja:Rzeszów
1

Pojedyncze instrukcje owijasz w try catch tam, gdzie spodziewasz się konkretnego błędu, który chcesz i możesz obsłużyć w konkretny sposób, np. błąd połączenia z bazą danych -> retry za 5 sekund, int.Parse nie przeszedł -> wyświetl błąd walidacji.
Dodatkowo możesz owinąć cały program żeby obsłużyć te błędy których nie przewidziałeś i np. zalogować błąd, wysłać telemetrię i wyświetlić komunikat "nieznany błąd, spróbuj ponownie".

edytowany 1x, ostatnio: mad_penguin
Grzegorz Świdwa
Grzegorz Świdwa
  • Rejestracja:ponad 5 lat
  • Ostatnio:ponad 4 lata
  • Postów:385
0
Kopiuj
int main()
{
     string UserName;
     try
     {
          UserName.ToString(); // Powstanie wyjątek. Dostaniesz NullreferenceException. Zamiast program się wyłączyć przekaże ten wyjątek do Catch()
     }
     catch(Exception e)
     {
          Console.WriteLine("Nie wykonasz operacji na UserName bo jest równy NULL");
     }
}
Zobacz pozostały 1 komentarz
WeiXiao
@Afish: wiesz może kiedy Console.WriteLine() rzuci wyjątek?
AF
@WeiXiao: Zależy, o jakim wyjątku mówisz. Chociażby to: string s = new string('a', 1000*1000*1000); Console.WriteLine(s) spowoduje wyjątek na .NET Framework na x86 (być może trzeba zrobić jeszcze dłuższego stringa, zależy od ASLR i szczęścia). Zobacz, że https://referencesource.microsoft.com/#mscorlib/system/io/textwriter.cs,468 alokuje tablicę długości string + 2, więc możesz dostać OOM. Możesz też zrobić StackOverflowException bez problemu.
WeiXiao
@Afish: a taki zwykły Console.WriteLine("dupa"); kojarzysz kiedy by mógł rzucić?
AF
Jak nie liczymy SOE, zamknięcia strumienia przez refleksję, braku uprawnień do konsoli, to zakładam, że nie powinien rzucić.
Grzegorz Świdwa
Grzegorz Świdwa
To oczywiste, że można po prostu sprawdzić string.IsNullOrEmpty()
ZK
  • Rejestracja:prawie 7 lat
  • Ostatnio:5 miesięcy
  • Postów:273
1

Po pierwsze. Nie każda instrukcja musi wyrzucić wyjątek.
Po drugie. Przed błędami można się bronić w różny sposób.Można np. sprawdzić poprawność wprowadzanych danych.
Instrukcji try catch używa się w ostateczności dlatego że to jest dodatkowe niepotrzebne obciążenie dla procesora.

Napisałeś jeszcze że najlepiej byłoby cały program ująć w instrukcję try.
Nie chodzi tylko o to, żeby przechwycić każdy błąd ale żeby wiedzieć jaki to jest błąd i odpowiednio obsłużyć dany błąd.

Radziłbym przeczytać chociaż jedną dobrą książkę o C#

edytowany 1x, ostatnio: Zimny Krawiec
Grzegorz Świdwa
Grzegorz Świdwa
  • Rejestracja:ponad 5 lat
  • Ostatnio:ponad 4 lata
  • Postów:385
1

Nawiązując do poprzedniego posta źle zrozumiałem pytanie. Myślałem, że pytasz się w jaki sposób używać try catch, a nie w jakich przypadkach.
Najprościej mówiąc try catch używa się wtedy, kiedy nie możesz wykryć błędu. W przykładzie pierwszym niewskazane jest używanie try catch, ponieważ możemy obsłużyć błędnie wpisane dane:

Kopiuj
bool Connect(string str)
    {
        if(string.IsNullOrEmpty(str))
            return false;
        return true;
    }
Kopiuj
if(Connect(null))
        {
              // wykonało się
        }
        else
        {
             // błąd
        }

W następnej metodzie nie możemy obsłużyć błędu i mamy dwa wyjścia:

Kopiuj
void Connect(string str)
    {
        if(string.IsNullOrEmpty(str))
            throw new ArgumentNullException();
    }

Wyjście 1: obsługa błędu przed wywołaniem

Kopiuj
if (string.IsNullOrEmpty(str))
        { }// obsługa błędu
        else
            Connect(str)

Wyjście 2: try catch

Kopiuj
try
        {
            Connect(str);
        }
        catch(Exception e)
        {

        }

Według mnie prawda jest taka, że chyba wszystko da się zrobić bez użycia try catch. Wystarczy mieć wiedzę na temat używanych metod, kontrolować wprowadzane dane zanim się ich użyje. Jednak - szczególnie w komunikacji sieciowej - przeszkód w połączeniu może być masa i te błędy nie muszą leżeć po naszej stronie. Wtedy warto użyć try catch aby pozbyć się nawet takiego problemu jak zanik internetu **podczas **pobierania danych z bazy danych (bo przecież można było wcześniej sprawdzić czy jest).

Wybór czy użyć czy nie leży po strony programisty. Musi on sam ocenić czy bez tego jego aplikacja będzie niezawodna

edytowany 1x, ostatnio: Grzegorz Świdwa
jasmina tmp
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad rok
  • Postów:10
0

Nie wiem czy wszystko się da zrobić bez użycia try catch, widziałem Apki korzystające z bibliotek trzecich które czasem sypnął wyjątkiem nie wiedzieć z czego i po co - bo coś się tam zmieniło.
Wyjątki są OK, lepiej nastawić się gdzieś catchem blisko wyjątku na poziomie kodu bo gdzieś tam na górze jest jakiś globalny catch ale może być różnie z diagnostyką problemu.
Drugi aspekt to co zrobić z wyjątkiem i z użytkownikiem.
Poprawcie mnie jeśli się mylę, ale aplikacja desktopowa jak nie przechwyci wyjątku to się zatrzyma z brzydkim stack tracem, aplikacja webowa typu Asp.Net pewnie przechwyci wyjątek na poziomie strony, lub aplikacji i wyświetli 404 ErrorPage.
Co ma zrobić z tym użytkownik?
Jak się da - to wyświetlić mu co należy poprawić, jeśli nie, a nie jest to krytyczna funkcjonalność to LOG Exception i puścić program dalej z jakimś WARN, a jeśli jest to krytyczna funkcjonalność to LOG + komunikat że się nie da ERROR + jakiś email do supportu.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.