Zpracování výjimek ve výrazech dotazů

V kontextu výrazu dotazu je možné volat jakoukoli metodu. Doporučujeme však vyhnout se volání jakékoli metody ve výrazu dotazu, který může vytvořit vedlejší efekt, například úpravu obsahu zdroje dat nebo vyvolání výjimky. Tento příklad ukazuje, jak se vyhnout vyvolání výjimek při volání metod ve výrazu dotazu bez porušení obecných pokynů .NET pro zpracování výjimek. Tyto pokyny uvádějí, že je přijatelné zachytit konkrétní výjimku, když pochopíte, proč je vyvolán v daném kontextu. Další informace naleznete v tématu Osvědčené postupy pro výjimky.

Poslední příklad ukazuje, jak tyto případy zpracovat, když při provádění dotazu musíte vyvolat výjimku.

Příklad 1

Následující příklad ukazuje, jak přesunout kód zpracování výjimek mimo výraz dotazu. To je možné pouze v případě, že metoda nezávisí na žádné proměnné místní pro dotaz. Je jednodušší řešit výjimky mimo výraz dotazu.

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

Všimněte si, že v předchozím příkladu catch (InvalidOperationException) zpracujte výjimku (nebo nezpracujte) způsobem, který je vhodný pro vaši aplikaci.

Příklad 2

V některých případech může být nejlepší odpovědí na výjimku, která je vyvoláná z dotazu, okamžité zastavení provádění dotazu. Následující příklad ukazuje, jak zpracovat výjimky, které mohou být vyvolány z textu dotazu. Předpokládejme, že SomeMethodThatMightThrow může potenciálně způsobit výjimku, která vyžaduje zastavení provádění dotazu.

Všimněte si, že try blok uzavře smyčku foreach , a ne samotný dotaz. Je to proto, že foreach smyčka je bodem, ve kterém se dotaz skutečně provádí. Další informace najdete v tématu Úvod k dotazům LINQ. Výjimka modulu runtime se vyvolá pouze při spuštění dotazu. Proto je nutné je zpracovat ve foreach smyčce.

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

Nezapomeňte zachytit jakoukoli výjimku, kterou očekáváte, že vyvoláte nebo provedete jakékoli nezbytné vyčištění v bloku finally.

Viz také