Практическое руководство. Обработка исключений в выражениях запросов (Руководство по программированию на C#)
Обновлен: Ноябрь 2007
В контексте выражения запроса можно вызывать любой метод. Однако не рекомендуется вызывать в выражении запроса методы, которые могут привести к возникновению побочных эффектов, таких как изменение содержимого источника данных или создание исключения. В этом примере показано, как избежать создания исключений при вызове методов в выражениях запросов без нарушения общих правил .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.
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.
*/
Компиляция кода
Создайте проект Visual Studio, предназначенный для платформы .NET Framework версии 3.5. По умолчанию в этом проекте имеется ссылка на файл System.Core.dll и директива using для пространства имен System.Linq.
Скопируйте код в созданный проект.
Нажмите клавишу F5, чтобы скомпилировать и запустить программу.
Нажмите любую клавишу для выхода из окна консоли.
См. также
Основные понятия
Выражения запросов LINQ (Руководство по программированию в C#)