Comment : gérer des exceptions dans des expressions de requête (Guide de programmation C#)

Il est possible d'appeler n'importe quelle méthode dans le contexte d'une expression de requête.Toutefois, nous vous recommandons d'éviter d'appeler n'importe quelle méthode dans une expression de requête qui peut créer un effet secondaire comme la modification du contenu de la source de données ou la levée d'une exception.Cet exemple indique comment éviter de lever des exceptions lorsque vous appelez des méthodes dans une expression de requête sans violer les indications générales du .NET Framework sur la gestion des exceptions.Ces indications déclarent qu'il est acceptable d'intercepter une exception spécifique lorsque vous comprenez pourquoi elle sera levée dans un contexte donné.Pour plus d'informations, consultez Meilleures pratiques pour la gestion des exceptions.

Le dernier exemple indique comment gérer ces cas lorsque vous devez lever une exception pendant l'exécution d'une requête.

Exemple

L'exemple suivant indique comment déplacer le code de gestion des exceptions à l'extérieur d'une expression de requête.C'est possible uniquement lorsque la méthode ne dépend d'aucune variable locale de la requête.

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

Dans certains cas, la meilleure réponse à une exception levée depuis l'intérieur d'une requête peut être d'arrêter immédiatement l'exécution de la requête.L'exemple suivant indique comment gérer des exceptions qui peuvent être levées depuis l'intérieur d'un corps de requête.Supposez que SomeMethodThatMightThrow peut potentiellement lever une exception qui requiert l'arrêt de l'exécution de la requête.

Notez que le bloc try englobe la boucle foreach et pas la requête elle-même.Cela est dû au fait que la boucle foreach est le point auquel la requête est réellement exécutée.Pour plus d'informations, consultez Introduction aux requêtes 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.
 */

Compilation du code

  • Créez un projet Visual Studio qui cible la version 3.5 du .NET Framework.Par défaut, le projet possède une référence à System.Core.dll et une directive using pour l'espace de noms System.Linq.

  • Copiez le code dans votre projet.

  • Appuyez sur F5 pour compiler et exécuter le programme.

Appuyez sur une touche pour quitter la fenêtre de console.

Voir aussi

Concepts

Expressions de requête LINQ (Guide de programmation C#)