Procedura: gestire le eccezioni nelle espressioni di query (Guida per programmatori C#)

È possibile chiamare qualsiasi metodo nel contesto di un'espressione di query. Si consiglia, tuttavia, di non chiamare qualsiasi metodo in un'espressione di query che può creare un effetto collaterale, quale la modifica del contenuto dell'origine dati o la generazione di un'eccezione. In questo esempio viene illustrato come evitare la generazione di eccezioni quando si chiamano metodi in un'espressione di query senza violare le linee guida di .NET Framework generali sulla gestione delle eccezioni. Tali linee guida stabiliscono che è accettabile intercettare un'eccezione specifica quando è evidente il motivo per cui verrà generata in un contesto specificato. Per ulteriori informazioni, vedere Gestione delle eccezioni.

Nell'esempio finale viene illustrato come gestire tali casi quando è necessario generare un'eccezione durante l'esecuzione di una query.

Esempio

Nell'esempio seguente viene illustrato come spostare codice di gestione dell'eccezione al di fuori di un'espressione di query. Questa operazione è possibile solo quando il metodo non dipende da qualsiasi variabile locale per la query.

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 alcuni casi, la migliore risposta a un'eccezione generata dall'interno di una query potrebbe essere l'arresto immediato dell'esecuzione della query. Nell'esempio seguente viene illustrato come gestire le eccezioni che potrebbero essere generate all'interno di un corpo di query. Si presuma che SomeMethodThatMightThrow possa potenzialmente causare un'eccezione che richiede l'arresto dell'esecuzione della query.

Si noti che il blocco try racchiude il ciclo foreach e non la query stessa, in quanto il ciclo foreach è il punto in corrispondenza del quale la query viene effettivamente eseguita. Per ulteriori informazioni, vedere la classe Introduzione alle query 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.
 */

Compilazione del codice

  • Creare un progetto Visual Studio per .NET Framework versione 3.5. Per impostazione predefinita, il progetto include un riferimento a System.Core.dll e una direttiva using per lo spazio dei nomi System.Linq.

  • Copiare il codice nel progetto.

  • Premere F5 per compilare ed eseguire il programma.

Premere un tasto per chiudere la finestra della console.

Vedere anche

Concetti

Espressioni di query LINQ (Guida per programmatori C#)