Behandeln von Ausnahmen in Abfrageausdrücken

Es ist möglich, jede Methode im Kontext eines Abfrageausdrucks aufzurufen. Es empfiehlt sich jedoch, Methoden in einem Abfrageausdruck aufzurufen, die Nebeneffekte wie die Änderung des Inhalts der Datenquelle oder das Auslösen einer Ausnahme erzeugen können. In diesem Beispiel wird veranschaulicht, wie Sie es beim Aufrufen von Methoden in Abfrageausdrücken vermeiden, Ausnahmen auszulösen, ohne gegen die allgemeinen .NET-Richtlinien für die Behandlung von Ausnahmen zu verstoßen. Gemäß dieser Richtlinien dürfen Sie eine bestimmte Ausnahme abfangen, wenn Sie wissen, warum sie in einem bestimmten Kontext ausgelöst wird. Weitere Informationen finden Sie unter Best Practices für Ausnahmen.

Im letzten Beispiel wird der Umgang mit diesen Fällen veranschaulicht, wenn Sie während der Ausführung einer Abfrage eine Ausnahme auslösen müssen.

Beispiel 1

Im folgenden Beispiel wird veranschaulicht, wie Sie den Ausnahmebehandlungscode aus einem Abfrageausdruck verschieben. Dies ist nur möglich, wenn die Methode von keiner für die Abfrage lokalen Variablen abhängig ist. Die Handhabung von Ausnahmen außerhalb des Abfrageausdrucks ist einfacher.

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

// DO THIS with a datasource that might
// throw an exception.
IEnumerable<int>? dataSource = null;
try
{
    dataSource = GetData();
}
catch (InvalidOperationException)
{
    Console.WriteLine("Invalid operation");
}

if (dataSource is not null)
{
    // 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());
    }
}

Beachten Sie, dass im catch (InvalidOperationException) im obigen Beispiel die Ausnahme so behandelt (oder nicht behandelt wird), wie sie für Ihre Anwendung geeignet ist.

Beispiel 2

In einigen Fällen ist die möglicherweise beste Antwort auf eine Ausnahme, die von einer Abfrage ausgelöst wird, die Ausführung der Abfrage sofort zu beenden. Im folgenden Beispiel wird der Umgang mit Ausnahmen veranschaulicht, die innerhalb eines Abfragetexts ausgelöst werden können. Angenommen dass SomeMethodThatMightThrow zu einer Ausnahme führen kann, derentwegen die Ausführung der Abfrage beenden werden muss.

Beachten Sie, dass der try-Block die foreach-Schleife und nicht die Abfrage selbst enthält. Das liegt daran, dass die foreach-Schleife der Punkt ist, an dem die Abfrage tatsächlich ausgeführt wird. Weitere Informationen finden Sie unter Einführung in LINQ-Abfragen. Die Runtime-Ausnahme wird nur ausgelöst, wenn die Abfrage ausgeführt wird. Daher müssen sie in der foreach-Schleife behandelt werden.

// Not very useful as a general purpose method.
string SomeMethodThatMightThrow(string s) =>
    s[4] == 'C' ?
        throw new InvalidOperationException() :
        @"C:\newFolder\" + s;

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

try
{
    foreach (var item in exceptionDemoQuery)
    {
        Console.WriteLine($"Processing {item}");
    }
}
catch (InvalidOperationException e)
{
    Console.WriteLine(e.Message);
}

/* Output:
    Processing C:\newFolder\fileA.txt
    Processing C:\newFolder\fileB.txt
    Operation is not valid due to the current state of the object.
 */

Denken Sie daran, alle Ausnahmen abzufangen, die Sie erwarten, und/oder alle erforderlichen Bereinigungen in einem endgültigen Block ausführen.

Siehe auch