try-catch (odwołanie w C#)

Instrukcja try-catch składa się z try blok, po której następuje jeden lub więcej catch klauzule, które określają procedury obsługi wyjątków różnych.

Uwagi

Gdy występuje wyjątek, common language runtime (CLR) szuka catch instrukcji, która obsługuje ten wyjątek.Jeśli metoda aktualnie nie ma takich catch blok wygląda CLR w metoda, że wywołano metodę bieżącej, i tak dalej w górę stosu wywołań.Jeśli nie catch znajduje się blok, a następnie wyświetla komunikat nieobsługiwany wyjątek do użytkownika CLR i zatrzymuje wykonywanie programu.

try Zawiera strzeżony kod, który może spowodować wyjątek.Blok jest wykonywane, dopóki jest wyjątek lub jest zakończone pomyślnie.Na przykład, następujące próby oddanych null obiekt podnosi NullReferenceException wyjątek:

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

Chociaż catch bez argumentów można użyć klauzuli złapać dowolnego typu wyjątek, to użycie nie jest zalecane.Ogólnie rzecz biorąc należy tylko złapać tych wyjątków, które wiedzą jak odzyskać z.W związku z tym, należy zawsze określić argument obiektu pochodzące z Exception na przykład:

catch (InvalidCastException e) 
{
}

Można użyć więcej niż jednego specyficznego catch w tej samej instrukcji try-catch klauzuli.W tym wypadku kolejność catch klauzule ważne jest, bo catch klauzule są badane w kolejności.Catch więcej wyjątków przed mniej konkretne.Kompilator generuje błąd, jeśli tak, że blokuje połowu, tak, że nigdy nie jest osiągalna później bloku.

A rzut instrukcja może być używana w catch bloku ponownie rzucić wyjątek, który jest wyłapywany przez catch instrukcji.Poniższy przykład wyodrębnia informacje o źródle, z IOException wyjątku, a następnie zgłasza wyjątek w metodzie nadrzędnej.

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 złapać jeden wyjątek i inny wyjątek.Po wykonaniu tej czynności należy określić wyjątek, który złowił jako wyjątek wewnętrzny, jak pokazano w poniższym przykładzie.

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

Można również ponowne wyjątek, gdy określony warunek jest spełniony, jak pokazano w poniższym przykładzie.

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

Od wewnątrz try bloku, zainicjować tylko zmienne, które są zadeklarowane w nim.W przeciwnym razie wyjątek może wystąpić przed zakończeniem wykonywania bloku.Na przykład w poniższym przykładzie kodu, zmienna n jest inicjowany wewnątrz try bloku.Przy próbie użycia tej zmiennej, poza try blok Write(n) instrukcja spowoduje wygenerowanie błędu kompilatora.

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 połowu, zobacz try-catch-finally.

Wyjątki w transmisji asynchronicznej metody

Metoda async jest oznaczona przez asynchroniczne modyfikator i zazwyczaj zawiera jeden lub więcej czekają na wyrażenia lub instrukcji.Wyrażenie oczekiwać stosuje się oczekiwać operatorowi Task lub Task.await Wyrażenie nie może występować w catch bloku lub finally bloku.

Kiedy sterowania osiąga await w metoda async postępu w metodzie jest zawieszone aż do zakończenia zadania oczekiwany.Po wykonaniu zadania w metodzie wznowić wykonywanie.Aby uzyskać więcej informacji, zobacz Programowanie asynchroniczne z Async i Await (C# i Visual Basic) i Przepływ sterowania w aplikacjach asynchronicznych (C# i Visual Basic).

Ukończone zadania, które await jest stosowana może być stan z powodu nieobsługiwany wyjątek w metodzie, która zwraca zadanie.Oczekiwanie na zadanie zgłasza wyjątek.Zadanie również może zakończyć się w stan Anulowane asynchronicznego procesu, który zwraca to zostało anulowane.Oczekujące na Anulowane zadania wyrzuca OperationCanceledException.Aby uzyskać więcej informacji na temat sposobu anulować proces asynchroniczny, zobacz Dostrajanie aplikacji Async (C# i Visual Basic).

Aby przechwycić tego wyjątku, czekają na zadanie w try blokować i przechwycić tego wyjątku w skojarzonym catch bloku.Na przykład zobacz sekcję "Przykład".

Zadanie może być stan, ponieważ wiele wyjątków wystąpił w metoda async oczekiwany.Na przykład zadanie może być wynikiem połączenia do Task.WhenAll.Gdy można oczekiwać takich zadań, jest tylko jeden z wyjątków złowionych i nie można przewidzieć, który będzie wyjątek.Na przykład zobacz sekcję "Przykład".

Przykład

W poniższym przykładzie try blok zawiera wywołanie ProcessString metoda, która może spowodować wyjątek.catch Zawiera klauzulę obsługi wyjątków, które po prostu wyświetla komunikat na ekranie.Gdy throw instrukcja jest wywoływana z wewnątrz MyMethod, system wyszukuje catch instrukcję i wyświetla komunikat 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.
     * */

W poniższym przykładzie są używane dwa bloki catch i najbardziej szczegółowych, który jest pierwszym, przechwycono.

Aby złapać najmniej określony wyjątek, można zastąpić instrukcji throw w ProcessString z następującą instrukcję: throw new Exception().

Jeśli blok catch specyficzne dla co najmniej po raz pierwszy w przykładzie, pojawia się następujący komunikat o błędzie: 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.
*/

Poniższy przykład ilustruje wyjątki dla metody komunikacji asynchronicznej.Aby wychwycić wyjątek, który rzuca zadanie asynchroniczne, należy umieścić await wyrażenie w try blok i przechwycić tego wyjątku w catch bloku.

Usuń oznaczenie jako throw new Exception linii w przykładzie w celu wykazania obsługi wyjątków.Zadanie IsFaulted właściwość jest ustawiona na True, zadania Exception.InnerException ustawiono właściwość wyjątku i wyjątek w catch bloku.

Usuń oznaczenie jako throw new OperationCancelledException wiersz, aby wykazać, co się dzieje, gdy ci cancelan proces asynchroniczny.Zadanie IsCanceled właściwość jest ustawiona na true, i wyjątek w catch bloku.W niektórych warunkach, które nie dotyczą tego przykładu, zadanie w IsFaulted właściwość jest ustawiona na true i IsCanceled jest ustawiona 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

Poniższy przykład ilustruje obsługę wyjątków, gdzie wiele zadań może spowodować wiele wyjątków.try Bloku czeka na zadania, który jest zwracany przez wywołanie do Task.WhenAll.Zadanie zostało wykonane, po zakończeniu trzy zadania, do których zastosowano WhenAll.

Każdy z trzech zadań powoduje wyjątek.catch Bloku iterację wyjątków, które znajdują się w Exception.InnerExceptions właściwość zadania, który został zwrócony przez 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#

Aby uzyskać więcej informacji, zobacz Specyfikacja języka C#. Specyfikacja języka jest ostatecznym źródłem informacji o składni i użyciu języka C#.

Zobacz też

Zadania

Porady: jawne zgłaszanie wyjątków

Informacje

Słowa kluczowe języka C#

Instrukcje try, throw i catch (C++)

Instrukcje obsługi wyjątków (odwołanie w C#)

throw (odwołanie w C#)

try-finally (odwołanie w C#)

Koncepcje

Przewodnik programowania w języku C#

Inne zasoby

Odwołanie w C#