try-catch (Справочник по C#)

Обновлен: Ноябрь 2007

Инструкция 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. Пример.

catch (InvalidCastException e) 
{
    throw (e);    // Rethrowing exception e
}

Также можно создать новое исключение. При этом задайте исключение, захваченное в качестве внутреннего исключения:

catch (InvalidCastException e) 
{
   // Can do cleanup work here.
    throw new CustomException("Error message here.", e);
}

Если требуется заново создать исключение, обрабатываемое предложением catch без параметров, используйте инструкцию throw без аргументов. Пример.

catch
{
    throw;
}

Внутри блока try следует инициализировать только те переменные, которые создаются в этом блоке. В противном случае исключение может возникнуть до завершения блока. Например, в следующем примере кода переменная x инициализируется внутри блока try. Попытка использовать эту переменную вне блока try в инструкции Write(x) приведет к ошибке компиляции: Использование локальной переменной x, которой не присвоено значение.

static void Main() 
{
    int x;
    try 
    {
        // Don't initialize this variable here.
        x = 123;
    }
    catch
    {
    }
    // Error: Use of unassigned local variable 'x'.
    Console.Write(x);
}

Дополнительные сведения о перехвате исключений см. в разделе 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 TryFinallyTest.Main() 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#:

  • 5.3.3.13 Инструкции try-catch

  • 8.10 Инструкция try

  • 16 Исключения

См. также

Задачи

Практическое руководство. Явное создание исключения

Основные понятия

Руководство по программированию в C#

Ссылки

Ключевые слова C#

The try, catch, and throw Statements

Операторы обработки исключений (Справочник по C#)

throw (Справочник по C#)

try-finally (Справочник по C#)

Другие ресурсы

Справочник по C#