Поделиться через


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#.

См. также

Задачи

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

Ссылки

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

try, catch, and throw Statements (C++)

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

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

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

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

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

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

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

Журнал изменений

Дата

Журнал

Причина

Июль 2010

Обновлены примеры throw.

Обратная связь от клиента.