Najlepsze praktyki w obsłudze wyjątków w C #

Obsługa wyjątków to technika obsługi błędów czasu wykonywania w kodzie aplikacji. Zasadniczo istnieją dwie kategorie wyjątków: wyjątki generowane przez aplikację i te, które są generowane przez środowisko wykonawcze. Z wyjątkami należy obchodzić się ostrożnie - należy dobrze wiedzieć, jak powinny być obsługiwane wyjątki i kiedy należy je obsłużyć w kodzie. W tym poście przedstawię kilka wskazówek i najlepszych praktyk dotyczących pracy z wyjątkami w języku C #.

Klasa bazowa dla wszystkich wyjątków w .NET to Exception. Wszystkie klasy wyjątków w hierarchii wyjątków pochodzą bezpośrednio lub pośrednio z tej klasy. Klasy ApplicationException i SystemException są pochodnymi klasy Exception. Środowisko uruchomieniowe języka wspólnego (CLR) zgłasza wystąpienie typu, który jest pochodną SystemException, gdy wystąpi błąd w czasie wykonywania. Zwróć uwagę, że nigdy nie należy przechwytywać SystemException ani zgłaszać wystąpienia SystemException w kodzie aplikacji.

Podczas tworzenia niestandardowych klas wyjątków należy zawsze pochodzić z klasy Exception, a nie z klasy ApplicationException. Jedną z przyczyn takiego stanu rzeczy jest to, że wystąpienie ApplicationException jest generowane przez aplikację, a nigdy przez środowisko wykonawcze. Rzucając wystąpienie ApplicationException w kodzie, po prostu zwiększysz stos wywołań bez dodawania dużej wartości.

Używanie obsługi wyjątków do zwracania informacji z metody jest złym podejściem projektowym. Jeśli zwracasz dane wyjątku ze swojej metody, projekt klasy jest nieprawidłowy i należy go ponownie odwiedzić. Należy pamiętać, że wyjątki są propagowane do wyższego poziomu w hierarchii wywołań metod i nie jest dobrą praktyką obsługiwanie wyjątków we wszystkich warstwach aplikacji. Wyjątek należy obsługiwać tak wysoko w hierarchii połączeń, jak to tylko możliwe - można wykorzystać wyjątek w warstwie prezentacji i wyświetlić użytkownikowi odpowiednie komunikaty, aby poinformować o dokładnym błędzie, który wystąpił.

Ponowne zgłoszenie wyjątku jest potrzebne, gdy chcesz wycofać transakcję bazy danych. Dobrą praktyką jest używanie określonych wyjątków, takich jak FileNotFoundException, IOException itp. Podczas pisania programów obsługi wyjątków, a następnie ogólnego bloku catch na końcu z klasą Exception. Zapewniłoby to dokładne poznanie błędu lub konkretnego błędu, który wystąpił. W witrynie MSDN stwierdza się: „Klasa ApplicationException nie dostarcza informacji o przyczynie wyjątków. W większości scenariuszy wystąpienia tej klasy nie powinny być generowane. W przypadkach, gdy tworzona jest instancja tej klasy, powinien być czytelny dla człowieka komunikat opisujący błąd przekazane do konstruktora ”.

Do obsługi wyjątków należy używać bloków try - catch, a do czyszczenia zasobów używanych w programie należy używać bloku final. Blok try zawierałby kod, który może zgłosić wyjątek, blok catch zostanie użyty do obsługi wyjątku zgłoszonego wewnątrz bloku try, a blok final zostanie użyty do zwolnienia wszelkich zasobów, z których korzystał program. Należy zauważyć, że ostatni blok ma gwarancję wykonania niezależnie od tego, czy wystąpił wyjątek, czy nie. Dlatego ostatecznie blok jest najlepszym miejscem w kodzie do czyszczenia zasobów, z których program korzystał.

Poniższy fragment kodu pokazuje, jak można wykorzystać instrukcję „using” do usuwania zasobów. Zauważ, że instrukcja „using” jest odpowiednikiem try - last block.

public string Read(string fileName)

{

try

{

string data;

using (StreamReader streamReader = new StreamReader(fileName))

{

data = streamReader.ReadToEnd();

}

return data;

}

catch (Exception)

{

throw;

}

}

Rzucanie wyjątków jest kosztowne. Ponowne wrzucanie wyjątków jest złą praktyką - w przypadku ponownego zgłaszania wyjątków można stracić ślad stosu.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

throw ex;

}

Zamiast tego użyj po prostu instrukcji „throw”, jeśli nie chcesz obsługiwać wyjątku w swoim programie obsługi wyjątków i propagować wyjątek w górę w hierarchii wywołań.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

throw;

}

Nigdy nie połykaj wyjątków - nigdy nie powinieneś ukrywać błędu, który wystąpił. Dobrą praktyką jest rejestrowanie wyjątków w aplikacji. Podczas rejestrowania wyjątków należy zawsze rejestrować wystąpienie wyjątku, aby rejestrowany był pełny ślad stosu, a nie tylko komunikat o wyjątku. Oto przykład, który to ilustruje.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

LogManager.Log(ex.ToString());

}

Nigdy nie należy używać wyjątków do propagowania lub wykonywania reguł biznesowych w aplikacji. Możesz uniknąć wyjątków w kodzie, używając odpowiedniej logiki walidacji. W większości przypadków należy unikać wyjątków - należy go używać tylko wtedy, gdy jest to konieczne.

Więcej informacji można znaleźć w tym artykule MSDN.