Gewusst wie: Behandeln von Ausnahmen in Abfrageausdrücken (C#-Programmierhandbuch)

Aktualisiert: November 2007

Es ist möglich, eine Methode im Kontext eines Abfrageausdrucks aufzurufen. Sie sollten es jedoch vermeiden, eine Methode in einem Abfrageausdruck aufzurufen, wenn dies zu unerwünschten Nebeneffekten führt, z. B. zum Ändern des Inhalts der Datenquelle oder zum Auslösen einer Ausnahme. Dieses Beispiel zeigt, wie Sie verhindern können, dass Ausnahmen ausgelöst werden, wenn Sie Methoden in einem Abfrageausdruck aufrufen, ohne gegen die allgemeinen .NET Framework-Richtlinien zur Ausnahmebehandlung zu verstoßen. Diese Richtlinien besagen, dass spezielle Ausnahmen abgefangen werden können, wenn Sie wissen, warum sie in einem bestimmten Kontext ausgelöst werden. Weitere Informationen hierzu finden Sie unter Ausnahmebehandlung.

Im letzten Beispiel wird gezeigt, wie Sie Fälle, in denen die Ausgabe einer Ausnahme während der Ausführung einer Abfrage erforderlich ist, behandeln können.

Beispiel

Im folgenden Beispiel wird gezeigt, wie Ausnahmebehandlungscode außerhalb eines Abfrageausdrucks verschoben wird. Dies ist nur möglich, wenn die Methode von keiner für die Abfrage lokalen Variablen abhängig ist.

class ExceptionsOutsideQuery
{
    static void Main()
    {
        // DO THIS with a datasource that might
        // throw an exception. It is easier to deal with
        // outside of the query expression.
        IEnumerable<int> dataSource;
        try
        {
            dataSource = GetData();
        }
        catch (InvalidOperationException)
        {
            // Handle (or don't handle) the exception 
            // in the way that is appropriate for your application.
            Console.WriteLine("Invalid operation");
            goto Exit;
        }

        // If we get here, it is safe to proceed.
        var query = from i in dataSource
                    select i * i;

        foreach (var i in query)
            Console.WriteLine(i.ToString());

        //Keep the console window open in debug mode
        Exit:
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    // A data source that is very likely to throw an exception!
    static IEnumerable<int> GetData()
    {
        throw new InvalidOperationException();
    }
}

In einigen Fällen ist die beste Antwort auf eine Ausnahme, die in einer Abfrage ausgelöst wird, das unmittelbare Anhalten des Abfragevorgangs. Im folgenden Beispiel wird gezeigt, wie Ausnahmen, die in einem Abfragetext ausgelöst werden könnten, behandelt werden. Annahme: SomeMethodThatMightThrow kann potenziell eine Ausnahme auslösen, woraufhin die Ausführung der Abfrage beendet werden muss.

Beachten Sie, dass der try-Block die foreach-Schleife einschließt, und nicht die Abfrage selbst. Das liegt daran, dass die foreach-Schleife der Punkt ist, an dem die Abfrage eigentlich ausgeführt wird. Weitere Informationen hierzu finden Sie unter Einführung in LINQ-Abfragen.

class QueryThatThrows
{
    static void Main()
    {
        // Data source.
        string[] files = { "fileA.txt", "fileB.txt", "fileC.txt" };

        // Demonstration query that throws.
        var exceptionDemoQuery =
            from file in files
            let n = SomeMethodThatMightThrow(file)
            select n;

        // Runtime exceptions are thrown when query is executed.
        // Therefore they must be handled in the foreach loop.
        try
        {
            foreach (var item in exceptionDemoQuery)
            {
                Console.WriteLine("Processing {0}", item);
            }
        }

        // Catch whatever exception you expect to raise
        // and/or do any necessary claanup in a finally block
        catch (InvalidOperationException e)
        {
            Console.WriteLine(e.Message);
        }

        //Keep the console window open in debug mode
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    // Not very useful as a general purpose method.
    static string SomeMethodThatMightThrow(string s)
    {
        if (s[4] == 'C')
            throw new InvalidOperationException();
        return @"C:\newFolder\" + s;
    }
}
/* Output:
    Processing C:\newFolder\fileA.txt
    Processing C:\newFolder\fileB.txt
    Operation is not valid due to the current state of the object.
 */

Kompilieren des Codes

  • Erstellen Sie ein Visual Studio-Projekt für .NET Framework, Version 3.5. Standardmäßig hat das Projekt einen Verweis auf System.Core.dll und eine using-Direktive für den System.Linq-Namespace.

  • Kopieren Sie den Code in Ihr Projekt.

  • Drücken Sie F5, um das Programm zu kompilieren und auszuführen.

Drücken Sie eine beliebige Taste, um das Konsolenfenster zu schließen.

Siehe auch

Konzepte

LINQ-Abfrageausdrücke (C#-Programmierhandbuch)