Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
59m 46s
Obsluga wyjątków jest kluczowym aspektem rozwoju odpornych aplikacji. Video Tima Coreya na temat "Obsluga wyjątków w C# - Kiedy je zlapac, gdzie je zlapac i jak je zlapac" dostarcza szczegółowego wyjasnienia, czym sa wyjątki, jak je obsługiwac i gdzie je obsługiwac.
Niniejszy artykuł ma na celu wyjasnienie obsługi wyjątków w C# za pomoca video Tima Coreya. Jest to potężna funkcja pozwalająca programistom zarządzać błędami i wyjątkowymi warunkami, które pojawiają się podczas wykonania programu. Używając bloków try, catch i finally, C# dostarcza strukturalny sposób na obsługę błędów w czasie wykonywania, logowanie wyjątków i utrzymanie przepływu programu.
Tim zaczyna od wyjaśnienia, że wielu programistów ma błędne spojrzenie na wyjątki i ich obsługę. Podkreśla znaczenie zrozumienia, czym są wyjątki i gdzie oraz jak je prawidłowo obsługiwać, aby tworzyć bardziej odporne aplikacje.
Tim tworzy aplikację konsolową w Visual Studio 2017, aby zademonstrować obsługę wyjątków. Zaleca używanie aplikacji konsolowych do testowania nowych tematów, ponieważ wymagają minimalnego przygotowania i są łatwe w obsłudze.
using System;
namespace ExceptionsDemo
{
class Program
{
static void Main(string[] args)
{
// Placeholder for input and output operations
Console.ReadLine();
}
}
}Imports System
Namespace ExceptionsDemo
Module Program
Sub Main(args As String())
' Placeholder for input and output operations
Console.ReadLine()
End Sub
End Module
End NamespaceTim dodaje bibliotekę klas do rozwiązania, aby zasymulować scenariusz rzeczywisty, w którym różne metody wywołują się nawzajem.

Usuwa domyślną klasę i tworzy nową klasę o nazwie DemoCode.
public class DemoCode
{
// Method to retrieve a number based on the provided position
public int GetNumber(int position)
{
int[] numbers = { 1, 4, 7, 2 };
return numbers[position];
}
// Intermediate method calls GetNumber
public int ParentMethod(int position)
{
return GetNumber(position);
}
// Top-level method calls ParentMethod
public int GrandparentMethod(int position)
{
return ParentMethod(position);
}
}Public Class DemoCode
' Method to retrieve a number based on the provided position
Public Function GetNumber(position As Integer) As Integer
Dim numbers As Integer() = {1, 4, 7, 2}
Return numbers(position)
End Function
' Intermediate method calls GetNumber
Public Function ParentMethod(position As Integer) As Integer
Return GetNumber(position)
End Function
' Top-level method calls ParentMethod
Public Function GrandparentMethod(position As Integer) As Integer
Return ParentMethod(position)
End Function
End ClassKlasa DemoCode zawiera metody, które wywołują się nawzajem, ostatecznie pobierając liczbę z tablicy na podstawie podanej pozycji.
Tim wyjaśnia, że aplikacja ma na celu demostrowanie porażek zamiast sukcesów. Wprowadza wyjątek wyjścia poza zakres, przekazując nieprawidłową pozycję do metody GrandparentMethod.
DemoCode demo = new DemoCode();
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");Dim demo As New DemoCode()
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")Uruchomienie powyższego kodu z nieprawidłową pozycją skutkuje wyjątkiem IndexOutOfRangeException. Tim pokazuje, jak debugger Visual Studio podświetla problem i dostarcza szczegółowych informacji o wyjątku.
Tim wyjaśnia powszechny błąd, który popełniają programiści, gdy pierwszy raz uczą się bloków try-catch. Często obejmują cały blok kodu, w którym spodziewają się wyjątku, co może prowadzić do niewłaściwej obsługi.
try
{
int output = 0;
output = numbers[position];
return output;
}
catch (Exception ex)
{
// Avoid returning default values that can mask the problem
return 0;
}Try
Dim output As Integer = 0
output = numbers(position)
Return output
Catch ex As Exception
' Avoid returning default values that can mask the problem
Return 0
End TryTim podkreśla, że to podejście jest problematyczne, ponieważ ukrywa wyjątek i kontynuuje wykonywanie kodu z nieprawidłowymi założeniami. Na przykład zwracanie 0 jako wartości domyślnej może nie być odpowiednie i może powodować dalsze problemy.
Tim podkreśla, że wyjątki dostarczają istotnych informacji o nieoczekiwanych stanach w aplikacji. Jeśli aplikacja kontynuuje w takim stanie bez właściwej obsługi, może to prowadzić do dalszych błędów i korupcji danych.
Zamiast połykania wyjątków, istotne jest, aby obchodzić się z nimi odpowiednio. Oto lepsze podejście:
try
{
return numbers[position];
}
catch (Exception ex)
{
// Log the exception or handle it appropriately
Console.WriteLine(ex.Message);
throw; // Re-throw the exception to be handled by a higher-level handler
}Try
Return numbers(position)
Catch ex As Exception
' Log the exception or handle it appropriately
Console.WriteLine(ex.Message)
Throw ' Re-throw the exception to be handled by a higher-level handler
End TryPrzez ponowne wyrzucenie wyjątku, upewniasz się, że problem jest propagowany i może być obsługiwany na wyższym poziomie, jeśli jest to konieczne.
Tim wyjaśnia, że podczas gdy niektóre wyjątki można obsłużyć bezpiecznie bez zawieszania aplikacji, ważne jest, aby dostarczać przydatne informacje zwrotne użytkownikowi. Na przykład, pokazując okno z komunikatem lub powiadomienie z opcją ponowienia operacji.
Tim demonstruje, jak używać właściwości StackTrace obiektu wyjątku, aby uzyskać szczegółowe informacje o miejscu wystąpienia wyjątku. Obejmuje to klasę, metodę i numer linii, co jest nieocenione podczas debugowania.
try
{
return numbers[position];
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
throw;
}Try
Return numbers(position)
Catch ex As Exception
Console.WriteLine(ex.StackTrace)
Throw
End TryWłaściwość StackTrace zapewnia pełny ślad wywołań stosu, pomagając programistom zlokalizować dokładne miejsce problemu.
Tim wyjaśnia, że właściwa obsługa wyjątków polega nie tylko na ich łapaniu, ale również na wiedzy, gdzie umieścić bloki try-catch. Kluczowym jest umieszczenie bloków try-catch na poziomie, gdzie mamy wystarczający kontekst, aby odpowiednio obsłużyć wyjątek.
Umieszczenie bloku try-catch głęboko w stosie wywołań często nie pozwala na skuteczne obsłużenie wyjątku, ponieważ brakuje kontekstu operacji wyższego poziomu.
// Deep level exception handling (not ideal)
try
{
return numbers[position];
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}' Deep level exception handling (not ideal)
Try
Return numbers(position)
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw
End TryUmieszczenie bloku try-catch na najwyższym poziomie, takiego jak w interfejsie użytkownika czy punkcie wejścia do aplikacji, pozwala obsłużyć wyjątki z pełnym kontekstem operacji.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryW ten sposób można dostarczyć bardziej informacyjne komunikaty użytkownikowi i zdecydować, czy aplikacja może kontynuować działanie, czy powinna zostać zakończona.
Tim podkreśla znaczenie informacji o śladzie stosu w diagnozowaniu wyjątków. Ślad stosu dostarcza szczegółowej historii wywołań, pokazując, gdzie wystąpił wyjątek i łańcuch wywołań metod, które do niego doprowadziły.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryTen wynik daje dokładną lokalizację wyjątku i ścieżkę przejścia przez kod, co ułatwia debugowanie i naprawę problemu.
Tim demonstruje, jak obsługiwać logikę na odpowiednim poziomie. Na przykład, jeśli metoda jest odpowiedzialna za otwieranie i zamykanie połączenia z bazą danych, powinna obsługiwać wyjątki, aby upewnić się, że zasoby są prawidłowo zarządzane.
public int GrandparentMethod(int position)
{
try
{
Console.WriteLine("Open database connection");
int output = ParentMethod(position);
Console.WriteLine("Close database connection");
return output;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Ensure the exception is propagated
}
}Public Function GrandparentMethod(position As Integer) As Integer
Try
Console.WriteLine("Open database connection")
Dim output As Integer = ParentMethod(position)
Console.WriteLine("Close database connection")
Return output
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Ensure the exception is propagated
End Try
End FunctionW tym przykładzie, jeśli wystąpi wyjątek, połączenie z bazą danych nie zostaje prawidłowo zamknięte, co prowadzi do potencjalnych wycieków zasobów. Dodając blok try-catch, można upewnić się, że połączenie jest zamknięte, nawet jeśli wystąpi wyjątek.
Tim wprowadza blok finally, który zapewnia, że pewien kod jest wykonywany niezależnie od tego, czy wyjątek wystąpi, czy nie. Jest to szczególnie przydatne do sprzątania zasobów, takich jak zamykanie połączeń z bazą danych.
public int GrandparentMethod(int position)
{
try
{
Console.WriteLine("Open database connection");
int output = ParentMethod(position);
return output;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Re-throw the exception to ensure it's handled by a higher-level handler
}
finally
{
Console.WriteLine("Close database connection");
}
}Public Function GrandparentMethod(position As Integer) As Integer
Try
Console.WriteLine("Open database connection")
Dim output As Integer = ParentMethod(position)
Return output
Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Re-throw the exception to ensure it's handled by a higher-level handler
Finally
Console.WriteLine("Close database connection")
End Try
End FunctionBlok finally działa po blokach try i catch, zapewniając, że połączenie jest zamknięte, nawet jeśli wystąpi wyjątek.
Tim wyjaśnia znaczenie ponownego wyrzucania wyjątków, aby przekazywać je w górę stosu wywołań. Pozwala to wysoko poziomowym obsługiwaczom na odpowiednią obróbkę wyjątków.
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw; // Re-throws the exception to be handled by the calling method
}Catch ex As Exception
Console.WriteLine(ex.Message)
Throw ' Re-throws the exception to be handled by the calling method
End TryPonowne wyrzucenie wyjątku za pomocą instrukcji throw; zapewnia, że pełen ślad stosu jest zachowany, dostarczając wartościowy kontekst do debugowania.
Tim demonstruje, jak wyjątki przepływają przez stos wywołań. Każda metoda sprawdza istnienie bloku try-catch i albo obsługuje wyjątek, albo przekazuje go w górę do wywołującej metody.
try
{
int result = demo.GrandparentMethod(4); // This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
Dim result As Integer = demo.GrandparentMethod(4) ' This will cause an IndexOutOfRangeException
Console.WriteLine($"The value at the given position is {result}")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryW tym przykładzie metoda GrandparentMethod łapie wyjątek, loguje go i ponownie go wyrzuca. Blok try-catch na najwyższym poziomie w aplikacji konsolowej następnie obsługuje wyjątek i wyświetla wiadomość o błędzie oraz ślad stosu.
Tim wyróżnia kilka powszechnych błędów, które programiści popełniają podczas obsługi wyjątków:
Zmiana śladu stosu i utrata wartościowego kontekstu.
Przykład:
catch (Exception ex)
{
// Incorrect
throw ex; // Rewrites stack trace
}
Tworzenie nowego wyjątku z niestandardowym komunikatem, ale utrata oryginalnego śladu stosu.
Przykład:
catch (Exception ex)
{
// Incorrect
throw new Exception("I blew up");
}
Tim wyjaśnia, jak stworzyć nowy wyjątek, zachowując oryginalny ślad stosu. Może to być przydatne, gdy chcesz dostarczyć bardziej znaczący komunikat o błędzie lub inny typ wyjątku, a jednocześnie zachować kontekst oryginalnego błędu.
catch (Exception ex)
{
throw new ArgumentException("You passed in bad data", ex);
}Catch ex As Exception
Throw New ArgumentException("You passed in bad data", ex)
End CatchPrzekazując oryginalny wyjątek (ex) jako wewnętrzny wyjątek, zachowujesz oryginalny ślad stosu, co jest kluczowe podczas debugowania.
Tim demonstruje, jak uzyskać dostęp do wiadomości oryginalnego wyjątku i śladu stosu podczas tworzenia nowego wyjątku.
catch (Exception ex)
{
Console.WriteLine("You passed in bad data");
Console.WriteLine(ex.StackTrace);
throw new ArgumentException("You passed in bad data", ex);
}Catch ex As Exception
Console.WriteLine("You passed in bad data")
Console.WriteLine(ex.StackTrace)
Throw New ArgumentException("You passed in bad data", ex)
End TryTo zapewnia, że wyjątek wyrzucony w górę stosu zawiera zarówno nowy komunikat, jak i szczegóły oryginalnego wyjątku.
Tim dostarcza metodę do przechodzenia przez wszystkie wewnętrzne wyjątki, aby wydobyć ich wiadomości i ślady stosu.
catch (Exception ex)
{
Exception inner = ex;
while (inner != null)
{
Console.WriteLine(inner.StackTrace);
inner = inner.InnerException;
}
throw;
}Catch ex As Exception
Dim inner As Exception = ex
While inner IsNot Nothing
Console.WriteLine(inner.StackTrace)
inner = inner.InnerException
End While
Throw
End TryPętla ta iteruje przez każdy wewnętrzny wyjątek, drukując jego ślad stosu, zapewniając, że wszystkie poziomy wyjątków są uwzględnione.
Tim omawia, jak obsługiwać różne typy wyjątków za pomocą wielu bloków catch. Pozwala to na specyficzną obsługę w zależności od typu wyjątku.
try
{
// Code that might throw an exception
}
catch (ArgumentException ex)
{
Console.WriteLine("You gave us bad information. Bad user!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
' Code that might throw an exception
Catch ex As ArgumentException
Console.WriteLine("You gave us bad information. Bad user!")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryW tym przykładzie wyjątek ArgumentException jest obsługiwany specjalnie poprzez wydruk niestandardowego komunikatu, podczas gdy wszystkie inne wyjątki są obsługiwane przez ogólny obsługiwacz drukujący komunikat wyjątku i ślad stosu.

Tim podkreśla znaczenie kolejności przy używaniu wielu bloków catch. Najbardziej specyficzne wyjątki powinny być łapane jako pierwsze, a następnie bardziej ogólne wyjątki.
try
{
// Code that might throw an exception
}
catch (ArgumentException ex)
{
Console.WriteLine("You gave us bad information. Bad user!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}Try
' Code that might throw an exception
Catch ex As ArgumentException
Console.WriteLine("You gave us bad information. Bad user!")
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)
End TryJeśli bardziej ogólny blok catch pojawi się przed specyficznym, złapie wszystkie wyjątki, a specyficzny blok nigdy nie zostanie osiągnięty, co prowadzi do błędów kompilacji.
Zaawansowany przewodnik wideo Tima Coreya na temat obsługi wyjątków w C# obejmuje kluczowe techniki tworzenia nowych wyjątków, zachowywania śladów stosu i efektywnego używania wielu bloków catch. Przestrzegając jego najlepszych praktyk, programiści mogą tworzyć odporne aplikacje, które obsługują wyjątki elegancko i dostarczają wartościowe informacje do debugowania.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy