try-catch (Справочник по C#)
Оператор try-catch состоит из блока try, за которым следует одно или несколько предложений catch, в которых определяются обработчики для различных исключений. При возникновении исключения среда CLR ищет оператор catch, который обрабатывает это исключение. Если выполняющийся в данный момент метод не содержит такого блока catch, то среда CLR рассматривает метод, который вызвал текущий метод, и т. д. по стеку вызовов. Если блок catch не найден, то среда CLR отображает пользователю сообщение о необработанном исключении и останавливает выполнение программы.
Блок try содержит защищаемый код, в котором могут происходить исключения. Этот блок выполняется до момента возникновения исключения или до своего успешного завершения. Например, следующая попытка приведения объекта null вызовет исключение NullReferenceException.
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
Хотя предложение catch можно использовать без аргументов для перехвата любого типа исключения, такой подход не рекомендуется. В общем случае следует перехватывать только те исключения, устранение причин которых известно. Поэтому следует всегда задавать аргумент объекта, производного от System.Exception. Например:
catch (InvalidCastException e)
{
}
В одном и том же операторе try-catch можно использовать несколько предложений catch. В этом случае будет иметь значение порядок следования предложений catch, поскольку предложения catch будут проверяться именно в этом порядке. Более общие исключения следует перехватывать после более частных. При упорядочивании блоков catch таким образом, чтобы последующий блок был недостижимым, компилятор вызовет ошибку.
В блок catch можно включить оператор throw, чтобы заново создать исключение, перехваченное оператором catch. В следующем примере извлекается источник информации из исключение IOException и затем выдается исключение для родительского метода.
catch (FileNotFoundException e)
{
// FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
// Extract some information from this exception, and then
// throw it to the parent method.
if (e.Source != null)
Console.WriteLine("IOException source: {0}", e.Source);
throw;
}
Можно перехватить одно исключение и создать другое исключение. При этом необходимо задать исключение, перехваченное в качестве внутреннего, как показано в следующем примере.
catch (InvalidCastException e)
{
// Perform some action here, and then throw a new exception.
throw new YourCustomException("Put your error message here.", e);
}
Кроме того, можно повторно создать исключение, если заданное условие выполнено, как показано в следующем примере.
catch (InvalidCastException e)
{
if (e.Data == null)
{
throw;
}
else
{
// Take some action.
}
}
Из блока try следует инициализировать только те переменные, которые в нем объявлены. В противном случае исключение может произойти до того, как завершится выполнение блока. Например, в следующем примере кода переменная n инициализируется внутри блока try. Попытка использовать эту переменную вне блока try в операторе Write(n) приведет к ошибке компиляции.
static void Main()
{
int n;
try
{
// Do not initialize this variable here.
n = 123;
}
catch
{
}
// Error: Use of unassigned local variable 'n'.
Console.Write(n);
}
Дополнительные сведения о перехвате исключений см. в разделе try-catch-finally.
Пример
В следующем примере блок try содержит обращение к методу ProcessString, который может вызвать исключение. В предложении catch содержится обработчик исключения, который просто выводит на экран сообщение. Если оператор throw вызывается из метода MyMethod, система осуществляет поиск оператора catch и выводит на экран сообщение Exception caught.
class TryFinallyTest
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
static void Main()
{
string s = null; // For demonstration purposes.
try
{
ProcessString(s);
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at TryFinallyTest.Main() Exception caught.
* */
В этом примере используются два оператора catch. Срабатывает первая из них, которая принимает более узкий диапазон исключений.
class ThrowTest3
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
static void Main()
{
try
{
string s = null;
ProcessString(s);
}
// Most specific:
catch (ArgumentNullException e)
{
Console.WriteLine("{0} First exception caught.", e);
}
// Least specific:
catch (Exception e)
{
Console.WriteLine("{0} Second exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at Test.ThrowTest3.ProcessString(String s) ... First exception caught.
*/
Если в предыдущем примере поменять местами предложения catch, появится следующее сообщение об ошибке.
A previous catch clause already catches all exceptions of this or a super type ('System.Exception')
Если же требуется перехватить исключение, относящееся к более широкому диапазону, необходимо изменить оператор throw следующим образом.
throw new Exception();
Спецификация языка C#
Дополнительные сведения см в Спецификация языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.
См. также
Задачи
Практическое руководство. Явное создание исключения
Ссылки
try, catch, and throw Statements (C++)
Операторы обработки исключений (Справочник по C#)
try-finally (Справочник по C#)
Основные понятия
Руководство по программированию на C#
Другие ресурсы
Журнал изменений
Дата |
Журнал |
Причина |
---|---|---|
Июль 2010 |
Обновлены примеры throw. |
Обратная связь от клиента. |