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


Практическое руководство. Обработка исключений в выражениях запросов (Руководство по программированию на C#)

В контексте выражения запроса можно вызывать любой метод.Однако не рекомендуется вызывать в выражении запроса методы, которые могут привести к возникновению побочных эффектов, таких как изменение содержимого источника данных или создание исключения.В этом примере показано, как избежать создания исключений при вызове методов в выражениях запросов без нарушения общих правил .NET Framework относительно обработки исключений.Эти правила гласят, что можно перехватывать определенные исключения, если известно, по какой причине они будут созданы в данном контексте.Дополнительные сведения см. в разделе Лучшие методики обработки исключений.

В итоговом примере показано, как обрабатывать случаи, когда необходимо создать исключение при выполнении запроса.

Пример

В следующем примере показано, как перенести код обработки исключений вне выражения запроса.Это возможно только в том случае, когда метод не зависит от переменных, являющихся локальными для запроса.

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

В некоторых случаях наилучшим решением при возникновении исключения в запросе является немедленная остановка выполнения запроса.В следующем примере показано, как обрабатывать исключения, которые могут возникнуть внутри тела запроса.Предположим, что SomeMethodThatMightThrow может вызвать исключение, для которого потребуется остановить выполнение запроса.

Обратите внимание, что блок try заключает в себя цикл foreach, а не сам запрос.Причина заключается в том, что цикл foreach — это точка, в которой запрос фактически выполняется.Дополнительные сведения см. в разделе Введение в запросы LINQ (C#).

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

Компиляция кода

  • Создайте проект Visual Studio, предназначенный для платформы .NET Framework версии 3.5.По умолчанию в проекте имеются ссылка на файл System.Core.dll и директива using (C#) для пространства имен System.Linq.

  • Скопируйте код в созданный проект.

  • Нажмите клавишу F5, чтобы скомпилировать и выполнить программу.

Нажмите любую клавишу для выхода из окна консоли.

См. также

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

Выражения запросов LINQ (Руководство по программированию на C#)