try-catch (odwołanie w C#)try-catch (C# Reference)

Instrukcja try-catch składa się z try bloku, po którym następuje co catch najmniej jedna klauzula, która określa programy obsługi dla różnych wyjątków.The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions.

Gdy wyjątek jest zgłaszany, środowisko uruchomieniowe języka wspólnego (CLR) wyszukuje catch instrukcję, która obsługuje ten wyjątek.When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception. Jeśli aktualnie wykonywana metoda nie zawiera takiego catch bloku, środowisko CLR przegląda metodę, która wywołała bieżącą metodę, i tak dalej na stosie wywołań.If the currently executing method does not contain such a catch block, the CLR looks at the method that called the current method, and so on up the call stack. Jeśli nie catch zostanie znaleziony żaden blok, środowisko CLR wyświetli komunikat o nieobsługiwanym wyjątku dla użytkownika i zakończy wykonywanie programu.If no catch block is found, then the CLR displays an unhandled exception message to the user and stops execution of the program.

try Blok zawiera chroniony kod, który może spowodować wyjątek.The try block contains the guarded code that may cause the exception. Blok jest wykonywany do momentu wyrzucania wyjątku lub zostanie ukończony pomyślnie.The block is executed until an exception is thrown or it is completed successfully. Na przykład następująca próba rzutowania null obiektu NullReferenceException zgłasza wyjątek:For example, the following attempt to cast a null object raises the NullReferenceException exception:

object o2 = null;
try
{
    int i2 = (int)o2;   // Error
}

catch Chociaż klauzula może być używana bez argumentów do przechwytywania dowolnego typu wyjątku, to użycie nie jest zalecane.Although the catch clause can be used without arguments to catch any type of exception, this usage is not recommended. Ogólnie rzecz biorąc, należy jedynie przechwycić te wyjątki, z których wiadomo, jak odzyskać.In general, you should only catch those exceptions that you know how to recover from. W związku z System.Exception tym zawsze należy określić argument obiektu pochodny na przykład:Therefore, you should always specify an object argument derived from System.Exception For example:

catch (InvalidCastException e)
{
}

Istnieje możliwość użycia więcej niż jednej klauzuli określonej catch w tej samej instrukcji try-catch.It is possible to use more than one specific catch clause in the same try-catch statement. W tym przypadku kolejność catch klauzul jest ważna, catch ponieważ klauzule są badane w kolejności.In this case, the order of the catch clauses is important because the catch clauses are examined in order. Przechwyć bardziej szczegółowe wyjątki przed bardziej szczegółowymi.Catch the more specific exceptions before the less specific ones. Kompilator generuje błąd w przypadku uporządkowania bloków catch w taki sposób, aby można było nigdy nie dotrzeć do późniejszego bloku.The compiler produces an error if you order your catch blocks so that a later block can never be reached.

Używanie catch argumentów jest jednym ze sposobów filtrowania wyjątków, które mają być obsługiwane.Using catch arguments is one way to filter for the exceptions you want to handle. Można również użyć filtru wyjątków, który dodatkowo bada wyjątek, aby zdecydować, czy go obsłużyć.You can also use an exception filter that further examines the exception to decide whether to handle it. Jeśli filtr wyjątku zwraca wartość false, wyszukiwanie programu obsługi jest kontynuowane.If the exception filter returns false, then the search for a handler continues.

catch (ArgumentException e) when (e.ParamName == "…")
{
}

Filtry wyjątków są preferowane do przechwytywania i ponownego zgłaszania (wyjaśniono poniżej), ponieważ filtry pozostawiają nienaruszony stos.Exception filters are preferable to catching and rethrowing (explained below) because filters leave the stack unharmed. Jeśli w późniejszym czasie program obsługi będzie zrzucał stos, zobaczysz miejsce, z którego pochodzi wyjątek, a nie tylko ostatnie miejsce, które zostało ponownie zgłoszone.If a later handler dumps the stack, you can see where the exception originally came from, rather than just the last place it was rethrown. Typowym zastosowaniem wyrażeń filtrów wyjątków jest rejestrowanie.A common use of exception filter expressions is logging. Można utworzyć filtr, który zawsze zwraca wartość false, która również prowadzi do dziennika, można rejestrować wyjątki w miarę ich wykonywania, bez konieczności ich obsługi i ponownego zgłaszania.You can create a filter that always returns false that also outputs to a log, you can log exceptions as they go by without having to handle them and rethrow.

Instrukcji throw można użyć w catch bloku, aby ponownie zgłosić wyjątek, który catch jest przechwytywany przez instrukcję.A throw statement can be used in a catch block to re-throw the exception that is caught by the catch statement. Poniższy przykład wyodrębnia informacje źródłowe z IOException wyjątku, a następnie zgłasza wyjątek do metody nadrzędnej.The following example extracts source information from an IOException exception, and then throws the exception to the parent method.

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;
}

Możesz przechwytywać jeden wyjątek i zgłosić inny wyjątek.You can catch one exception and throw a different exception. Gdy to zrobisz, określ wyjątek, który został przechwycony jako wyjątek wewnętrzny, jak pokazano w poniższym przykładzie.When you do this, specify the exception that you caught as the inner exception, as shown in the following example.

catch (InvalidCastException e) 
{
    // Perform some action here, and then throw a new exception.
    throw new YourCustomException("Put your error message here.", e);
}

Możesz również ponownie zgłosić wyjątek, gdy określony warunek ma wartość true, jak pokazano w poniższym przykładzie.You can also re-throw an exception when a specified condition is true, as shown in the following example.

catch (InvalidCastException e)
{
    if (e.Data == null)
    {
        throw;
    }
    else
    {
        // Take some action.
    }
}

Uwaga

Istnieje również możliwość użycia filtru wyjątków, aby uzyskać podobny wynik w sposób, który jest w sposób bardziej przejrzysty (a także bez modyfikowania stosu, jak wyjaśniono wcześniej w tym dokumencie).It is also possible to use an exception filter to get a similar result in an often cleaner fashion (as well as not modifying the stack, as explained earlier in this document). Poniższy przykład ma podobne zachowanie w przypadku wywołujących w poprzednim przykładzie.The following example has a similar behavior for callers as the previous example. Funkcja zwraca InvalidCastException z powrotem do obiektu wywołującego, e.Data gdy nullma wartość.The function throws the InvalidCastException back to the caller when e.Data is null.

catch (InvalidCastException e) when (e.Data != null) 
{
    // Take some action.
}

Z wewnątrz try bloku należy inicjować tylko zmienne, które są w nim zadeklarowane.From inside a try block, initialize only variables that are declared therein. W przeciwnym razie może wystąpić wyjątek przed ukończeniem wykonywania bloku.Otherwise, an exception can occur before the execution of the block is completed. Na przykład, w poniższym przykładzie kodu zmienna n jest inicjowana try wewnątrz bloku.For example, in the following code example, the variable n is initialized inside the try block. Próba użycia tej zmiennej poza try blokiem Write(n) w instrukcji spowoduje wygenerowanie błędu kompilatora.An attempt to use this variable outside the try block in the Write(n) statement will generate a compiler error.

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);
}

Aby uzyskać więcej informacji na temat catch, zobacz try-catch-finally.For more information about catch, see try-catch-finally.

Wyjątki w metodach asynchronicznychExceptions in async methods

Metoda asynchroniczna jest oznaczona przez modyfikator Async i zwykle zawiera co najmniej jedno wyrażenie lub instrukcje await.An async method is marked by an async modifier and usually contains one or more await expressions or statements. Wyrażenie await stosuje operator await do Task lub Task<TResult>.An await expression applies the await operator to a Task or Task<TResult>.

Gdy kontrolka osiągnie await wartość w metodzie asynchronicznej, postęp w metodzie jest zawieszony do momentu zakończenia zadania oczekiwania.When control reaches an await in the async method, progress in the method is suspended until the awaited task completes. Po zakończeniu zadania wykonywanie może zostać wznowione w metodzie.When the task is complete, execution can resume in the method. Aby uzyskać więcej informacji, zobacz programowanie asynchroniczne z asynchroniczne i oczekujące i przepływ sterowania w programach asynchronicznych.For more information, see Asynchronous Programming with async and await and Control Flow in Async Programs.

Ukończone zadanie, do którego await zastosowano, może być w stanie awarii z powodu nieobsłużonego wyjątku w metodzie, która zwraca zadanie.The completed task to which await is applied might be in a faulted state because of an unhandled exception in the method that returns the task. Oczekiwanie na zadanie zgłosi wyjątek.Awaiting the task throws an exception. Zadanie można także zakończyć w stanie anulowanym, jeśli asynchroniczny proces zwraca go.A task can also end up in a canceled state if the asynchronous process that returns it is canceled. Oczekiwanie na anulowane zadanie OperationCanceledExceptionwyrzuca.Awaiting a canceled task throws an OperationCanceledException. Aby uzyskać więcej informacji o tym, jak anulować proces asynchroniczny, zobacz dostrajanie aplikacji asynchronicznej.For more information about how to cancel an asynchronous process, see Fine-Tuning Your Async Application.

Aby wychwycić wyjątek, oczekiwanie na zadanie w try bloku i Przechwyć wyjątek w skojarzonym catch bloku.To catch the exception, await the task in a try block, and catch the exception in the associated catch block. Aby zapoznać się z przykładem, zobacz sekcję dotyczącą przykładu metody asynchronicznej .For an example, see the Async method example section.

Zadanie może być w stanie nieprawidłowym, ponieważ wystąpiły wiele wyjątków w metodzie asynchronicznej oczekiwania.A task can be in a faulted state because multiple exceptions occurred in the awaited async method. Na przykład zadanie może być wynikiem wywołania metody Task.WhenAll.For example, the task might be the result of a call to Task.WhenAll. Podczas oczekiwania na takie zadanie zostanie przechwycony tylko jeden z wyjątków i nie będzie można przewidzieć, który wyjątek zostanie przechwycony.When you await such a task, only one of the exceptions is caught, and you can't predict which exception will be caught. Aby zapoznać się z przykładem, zapoznaj się z sekcją przykład Task. WhenAll .For an example, see the Task.WhenAll example section.

PrzykładExample

W poniższym przykładzie try blok zawiera wywołanie ProcessString metody, która może spowodować wyjątek.In the following example, the try block contains a call to the ProcessString method that may cause an exception. catch Klauzula zawiera procedurę obsługi wyjątków, która po prostu wyświetla komunikat na ekranie.The catch clause contains the exception handler that just displays a message on the screen. Gdy instrukcja jest wywoływana z wewnątrz MyMethod, system szuka catch instrukcji i wyświetla komunikat Exception caught. throwWhen the throw statement is called from inside MyMethod, the system looks for the catch statement and displays the message 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.
 * */

Przykład dwóch bloków catchTwo catch blocks example

W poniższym przykładzie są używane dwa bloki catch, a najbardziej konkretny wyjątek, który jest pierwszy, jest przechwytywany.In the following example, two catch blocks are used, and the most specific exception, which comes first, is caught.

Aby przechwycić najmniejszy konkretny wyjątek, można zastąpić instrukcję ProcessString throw przy użyciu następującej instrukcji:. throw new Exception()To catch the least specific exception, you can replace the throw statement in ProcessString with the following statement: throw new Exception().

W przypadku umieszczenia bloku catch o najniższym poziomie najpierw w tym przykładzie zostanie wyświetlony następujący komunikat o błędzie A previous catch clause already catches all exceptions of this or a super type ('System.Exception'):.If you place the least-specific catch block first in the example, the following error message appears: A previous catch clause already catches all exceptions of this or a super type ('System.Exception').

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.
*/

Przykład metody asynchronicznejAsync method example

Poniższy przykład ilustruje obsługę wyjątków dla metod asynchronicznych.The following example illustrates exception handling for async methods. Aby przechwytywać wyjątek, który generuje zadanie asynchroniczne, umieść await wyrażenie try w bloku i catch Przechwyć wyjątek w bloku.To catch an exception that an async task throws, place the await expression in a try block, and catch the exception in a catch block.

Usuń komentarz throw new Exception wiersza z przykładu, aby zademonstrować obsługę wyjątków.Uncomment the throw new Exception line in the example to demonstrate exception handling. IsFaulted Właściwość zadania jest ustawiona na True, Exception.InnerException właściwość zadania jest ustawiana na wyjątek catch , a wyjątek jest przechwytywany w bloku.The task's IsFaulted property is set to True, the task's Exception.InnerException property is set to the exception, and the exception is caught in the catch block.

Usuń komentarz z throw new OperationCanceledException wiersza, aby zademonstrować, co się dzieje po anulowaniu procesu asynchronicznego.Uncomment the throw new OperationCanceledException line to demonstrate what happens when you cancel an asynchronous process. IsCanceled Właściwość zadania jest ustawiona na true, a catch wyjątek jest przechwytywany w bloku.The task's IsCanceled property is set to true, and the exception is caught in the catch block. W przypadku niektórych warunków, które nie dotyczą tego IsFaulted przykładu, właściwość zadania jest ustawiona na true i IsCanceled jest ustawiona na. falseUnder some conditions that don't apply to this example, the task's IsFaulted property is set to true and IsCanceled is set to false.

public async Task DoSomethingAsync()
{
    Task<string> theTask = DelayAsync();

    try
    {
        string result = await theTask;
        Debug.WriteLine("Result: " + result);
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception Message: " + ex.Message);
    }
    Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
    Debug.WriteLine("Task IsFaulted:  " + theTask.IsFaulted);
    if (theTask.Exception != null)
    {
        Debug.WriteLine("Task Exception Message: "
            + theTask.Exception.Message);
        Debug.WriteLine("Task Inner Exception Message: "
            + theTask.Exception.InnerException.Message);
    }
}

private async Task<string> DelayAsync()
{
    await Task.Delay(100);

    // Uncomment each of the following lines to
    // demonstrate exception handling.

    //throw new OperationCanceledException("canceled");
    //throw new Exception("Something happened.");
    return "Done";
}

// Output when no exception is thrown in the awaited method:
//   Result: Done
//   Task IsCanceled: False
//   Task IsFaulted:  False

// Output when an Exception is thrown in the awaited method:
//   Exception Message: Something happened.
//   Task IsCanceled: False
//   Task IsFaulted:  True
//   Task Exception Message: One or more errors occurred.
//   Task Inner Exception Message: Something happened.

// Output when a OperationCanceledException or TaskCanceledException
// is thrown in the awaited method:
//   Exception Message: canceled
//   Task IsCanceled: True
//   Task IsFaulted:  False

Task. WhenAll — przykładTask.WhenAll example

Poniższy przykład ilustruje obsługę wyjątków, gdy wiele zadań może skutkować wieloma wyjątkami.The following example illustrates exception handling where multiple tasks can result in multiple exceptions. Blok oczekuje zadania, które jest zwracane przez Task.WhenAllwywołanie metody. tryThe try block awaits the task that's returned by a call to Task.WhenAll. Zadanie zostanie ukończone, gdy zostaną wykonane trzy zadania, do których zastosowano WhenAll.The task is complete when the three tasks to which WhenAll is applied are complete.

Każdy z tych trzech zadań powoduje wyjątek.Each of the three tasks causes an exception. Blok wykonuje iterację Exception.InnerExceptions w wyjątkach, które są dostępne we właściwości zadania, które zostało zwrócone przez Task.WhenAll. catchThe catch block iterates through the exceptions, which are found in the Exception.InnerExceptions property of the task that was returned by Task.WhenAll.

public async Task DoMultipleAsync()
{
    Task theTask1 = ExcAsync(info: "First Task");
    Task theTask2 = ExcAsync(info: "Second Task");
    Task theTask3 = ExcAsync(info: "Third Task");

    Task allTasks = Task.WhenAll(theTask1, theTask2, theTask3);

    try
    {
        await allTasks;
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception: " + ex.Message);
        Debug.WriteLine("Task IsFaulted: " + allTasks.IsFaulted);
        foreach (var inEx in allTasks.Exception.InnerExceptions)
        {
            Debug.WriteLine("Task Inner Exception: " + inEx.Message);
        }
    }
}

private async Task ExcAsync(string info)
{
    await Task.Delay(100);
    
    throw new Exception("Error-" + info);
}

// Output:
//   Exception: Error-First Task
//   Task IsFaulted: True
//   Task Inner Exception: Error-First Task
//   Task Inner Exception: Error-Second Task
//   Task Inner Exception: Error-Third Task

specyfikacja języka C#C# language specification

Aby uzyskać więcej informacji, zobacz sekcję try instrukcji C# specyfikacji języka.For more information, see The try statement section of the C# language specification.

Zobacz takżeSee also