Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

C#6 : amélioration de la gestion des exceptions

[new:30/10/2014]Roslyn qu’on peut appeler maintenant C# 6 va bientôt être une réalité, en attendant on peut en découvrir certains aspects, par exemple du côté des exceptions…

Roslyn / C# 6

J’ai déjà abordé en avant première certains des aspects de C# 6 dans un billet du 15 mai dernier, je renvoie ainsi le lecteur intéressé à ce dernier qui y trouvera d’autres annonces et quelques mots sur les nouveautés touchant la gestion des exceptions.

Les exceptions de C# 6

Justement il ne s’agissait que de quelques mots. Aujourd’hui on peut présenter ces avancées de façon plus complète. Allons-y !

Les améliorations de la gestion des exceptions ne sont pas faramineuses disons-le tout de suite, mais elles sont assez importantes. Il y a deux avancées principales. La première est une amélioration de async/await et la seconde est le support du filtrage des exceptions.

C# 5 a introduit async/await dont je ne parlerais pas ici renvoyant le lecteur à mes billets sur le sujet (dont celui du 23 juin dernier qui est assez précis). Avec cet ajout les développeurs ont gagné beaucoup dans la simplification de l’écriture du code asynchrone laissant au compilateur la charge fastidieuse de générer les callbacks sous-jacents. De même grâce à ces mots clés contextuels il a été possible d’aborder le pattern TAP (Task-based Asynchronous Pattern) de façon plus simple et naturelle.

Hélas, l’équipe en charge de ces améliorations n’a pas eu le temps de finir le travail dans les blocs try/catch/finally. Ainsi, si await était utilisable dans le corps d’un Try, il n’était pas possible de s’en servir dans le Catch ou le Finally.

Le besoin a été un peu sous-estimé et la priorité n’a pas été donnée à une implémentation complète de async/await dans les gestionnaires d’exception. Le succès de ces derniers et la recherche d’un code toujours plus asynchrone ont d’un autre côté tenté de plus en plus de développeurs d’utiliser une gestion asynchrone des exceptions, impossible en C# 5 donc. Il y avait là un trou à boucher pour terminer l’édifice.

Traitement asynchrone du Catch

Heureusement les choses ont avancé et C# 6 ne possède plus cette limite ! Il est donc possible de gérer de façon asynchrone le code d’un Catch ou d’un Finally comme le montre le code ci-dessous (sur la partie Catch uniquement)  :

try
{
    var webRequest =  WebRequest.Create("https://www.e-naxos.com");
    var response =  await webRequest.GetResponseAsync();
    // ...
}
catch (WebException exception)
{
    await LogError(exception);
}

 

Filtrage des exceptions

Une autre avancée dans la gestion des exceptions de C# 6 est le filtrage ou plus précisément le support des filtres d’exception. Pour une fois c’est C# qui était en retard et il ne fait donc ici que rattraper VB et F#.

Le filtrage des exceptions existait déjà sur le type de ces dernières depuis les débuts de C#, il s’agit donc ici de spécialiser ce filtre pour affiner les conditions de ce filtrage. Dans la pratique on peut ainsi ajouter un “if” après le Catch pour cibler certaines valeurs de l’exception qui ne dépendent pas seulement du nom de sa classe mais des informations que l’instance véhicule. Un bout de code rendra cela plus parlant :

public void Test()
{
    try
    {
        throw new Win32Exception(Marshal.GetLastWin32Error());
    }
    catch (Win32Exception exception) if (exception.NativeErrorCode == 0x00042)
    {
        // traitement de l'erreur native 42 de l'OS
    }
}

 

Tout ce trouve donc dans ce “if” ajouté après le “catch”. Ce dernier filtre sur la classe de l’exception et le “if” permet d’affiner sur le contenu réel de l’exception qui arrive. Ici on ne souhaite que gérer les exceptions de type Win32Exception (natives donc) et uniquement celle dont le code d’erreur natif est 42.

Bien qu’assez simple cette nouveauté est intéressante à plus d’un titre. Car beaucoup de nouveautés de C# 6 pourrait s’écrire en C# 5 avec plus de code mais celle-ci est totalement impossible à simuler proprement. Il faut en C# 5 attraper toutes les exceptions d’une classe donnée puis dans le bloc Catch vérifier si on désire ou non traiter l’erreur, dans la négative il faut faire un re-throw de l’exception. Mécaniquement c’est un émulation assez proche mais techniquement elle ne l’est pas notamment dans le suivi du StackTrace par exemple.

Conclusion

Rien d’énorme en soi, mais deux ajouts qui rendent C# encore plus fin, plus subtile et précis. Il ne faut plus s’attendre à des ajouts aussi énormes que LINQ par exemple, même si async/await me semble d’une importance capitale tout comme Parallel-LINQ mais cela a été fait dans C# 5, la version 6 arrive avec son nouveau moteur, en open source, et quelques ajouts intéressants. C’est la version 7 qui sera certainement plus marquante pour le développeur mais il est trop tôt pour en parler, la 6 n’étant pour l’instant que simplement testable dans une preview disponible ici : https://roslyn.codeplex.com/. Le passage du projet Roselyn à celui de C# 6 en open source est déjà en soi quelque chose d’énorme ne l’oublions pas !

blog comments powered by Disqus