Voici un exemple d'un programme Hello world typique, écrit en C# :
using System; class HelloWorld { public static void Main() { Console.WriteLine("Hello World!"); } }
Gestion des exceptions
C# possède les instructions try et catch permettant de gérer les exceptions (comportement non attendu des instructions du programme), similaires dans la syntaxe à ceux du C++.
Exemple de code tentant de créer un fichier "document.txt" sur le serveur "Toto":
try { // Tentative de création du fichier 'document.txt' sur le serveur 'Toto' File.Create(@"\\toto\document.txt"); } catch { // Impossible de contacter le server Toto MessageBox.Show("L'application n'arrive pas à créer le fichier 'document.txt' sur le serveur 'Toto' !", "Alerte"); }
Notez l'utilisation d'une chaîne de caractère verbatim : le caractère arobase précède le guillemet donc l'anti-slash n'est pas doublé. Ce genre de chaîne de caractères est pratique pour les chemins sous Windows.
Dans cet exemple, la fonction File.Create retourne un flux (FileStream), ou elle peut lancer une exception si une erreur s'est produite (problème de connexion par exemple).
Dans cet exemple, aucune information sur l'exception n'est obtenue : on cherche juste à savoir si le programme ne s'est pas comporté normalement, auquel cas on arrive dans le bloc catch.
Contrairement au C++ qui n'a pas de type d'exceptions, toute exception C# est héritée (ou une instance) du type System.Exception, ainsi si on cherche à savoir ce qui s'est passé, une solution simple reste d'obtenir une référence vers l'exception de la manière suivante :
try { // Tentative de création du fichier 'document.txt' sur le serveur 'Toto' File.Create(@"\\toto\document.txt"); } catch(Exception err) { // Impossible de contacter le server Toto MessageBox.Show("L'application n'arrive pas à créer le fichier 'document.txt' sur le serveur 'Toto' ! Erreur:" + err.Message, "Alerte"); }
Ainsi, une information complète sera retournée, décrivant la nature de l'exception qui s'est produite.
En fonction des fonctions appelées, le framework .NET fournit la liste des exceptions que l'appel est susceptible de retourner en cas d'erreur. Dans le cas de la fonction 'Create' voici la liste des exceptions possibles:
- System.UnauthorizedAccessException
- System.ArgumentException
- System.ArgumentNullException
- System.IO.PathTooLongException
- System.IO.DirectoryNotFoundException
- System.IO.IOException
- System.NotSupportedException
try { // Tentative de création du fichier 'document.txt' sur le serveur 'Toto' File.Create(@"\\toto\do?ument.txt"); } catch(System.ArgumentException ArgumentErr) { // L'argument n'est pas valable. Le nom de fichier 'do?ument.txt' n'est pas valable MessageBox.Show("L'argument n'est pas valable. Le nom de fichier 'do?ument.txt' n'est pas valable ! Erreur:" + ArgumentErr.Message, "Alerte"); } catch(Exception err) { // Impossible de contacter le server Toto MessageBox.Show("L'application n'arrive pas à créer le fichier 'document.txt' sur le serveur 'Toto' ! Erreur:" + err.Message, "Alerte"); }
De la même manière qu'en C++, l'envoi d'une exception se fait avec le mot-clef throw :
public uint Divide(uint num, uint div) //Fonction de division dans N { if(div == 0) throw new Exception ("Division par 0 !"); if(num < div) throw new Exception ("num est strictement inférieur à div : le résultat de la division ne sera pas un entier naturel !"); return num / div; } //Code ailleurs : try { Divide(12, 6); //Retourne 2, aucune exception Divide(10, 20); //Exception, cette division ne donne aucun résultat dans N Divide(10, 0); //Exception, division par zéro impossible } catch (Exception e) { MessageBox.Show("L'erreur suivante a été retournée :\n" + e.Message, "Alerte"); }
L'envoi d'une exception (via throw) ou la levée d'une exception (dans un bloc try/catch) met immédiatement fin au bloc en cours. Ainsi, si div est nul, le code de la fonction Divide s'arrêtera à la ligne 2. De même, dans l'exemple précédent, la troisième fonction Divide ne sera jamais exécutée à cause de la levée d'une exception lors du deuxième appel à Divide. Une exception non attrapée (« catchée ») - c'est-à-dire que l'application n'a pas encadré le code lançant l'exception par un bloc catch approprié - met fin à l'application immédiatement sous la forme d'une exception de type UnhandledException (exception non gérée en français).
Comme en Java, il est possible d'ajouter un bloc finally pour exécuter une série d'instructions, quoi qu'il se passe (exception lancée ou non). Cela est utile pour libérer des ressources quel que soit ce qui peut se passer entre la prise de ressource et la libération. Exemple typique : lecture de fichiers
FileStream fs = new FileStream(@"C:\Fichier.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite); // arrivé ici, le fichier est ouvert try { // ... opérations de lecture / écriture pouvant lancer des exceptions ... } finally { // fermer le fichier quoi qu'il se passe : fs.Close(); }