c# wikibook

Upload: mrollandatos

Post on 09-Jul-2015

254 views

Category:

Documents


1 download

TRANSCRIPT

Programmation C#

PDF gnrs en utilisant latelier en source ouvert mwlib . Voir http://code.pediapress.com/ pour plus dinformations. PDF generated at: Sun, 02 Oct 2011 06:07:50 UTC

ContenusArticlesProgrammation C sharp Programmation C sharp/Introduction Programmation C sharp/Compilation Programmation C sharp/Un premier programme 1 2 3 6 9 9 10 15 18 20 23 24 28 33 35 41 48 53 55 59 62 65 65 66 69 73 76 85 89 92 93

Le langageProgrammation C sharp/Les commentaires Programmation C sharp/Les espaces de noms Programmation C sharp/Les variables et les constantes Programmation C sharp/Les types de base et les dclarations Programmation C sharp/Les tableaux Programmation C sharp/Les objets Programmation C sharp/Les classes Programmation C sharp/Les fonctions Programmation C sharp/Proprits et indexeurs Programmation C sharp/Les oprateurs Programmation C sharp/Structures de contrle Programmation C sharp/Hritage de classes Programmation C sharp/Classe abstraite Programmation C sharp/Les exceptions Programmation C sharp/Structures et numrations Programmation C sharp/Interfaces

Programmation avanceProgrammation C sharp/Type partiel Programmation C sharp/Surcharge des oprateurs Programmation C sharp/Directives du prprocesseur Programmation C sharp/Documentation XML des classes Programmation C sharp/Attributs Programmation C sharp/Delegates et events Programmation C sharp/Types gnriques Programmation C sharp/Appel de plateforme Programmation C sharp/Code non vrifi

API .NetProgrammation C sharp/Interfaces graphiques Programmation C sharp/Interfaces graphiques/Graphique vectoriel Programmation C sharp/Fonctions asynchrones Programmation C sharp/Threads et synchronisation Programmation C sharp/Processus Programmation C sharp/Entres-sorties Programmation C sharp/La srialisation Programmation C sharp/Les fichiers Programmation C sharp/Programmation rseau Programmation C sharp/Excution distante

96 96 99 102 103 115 116 119 123 127 128 132 132 133

RessourcesProgrammation C sharp/Bibliographie et liens Programmation C sharp/Index des mots-cls du langage

RfrencesSources et contributeurs de larticle Source des images, licences et contributeurs 143 144

Licence des articlesLicence 145

Programmation C sharp

1

Programmation C sharpProgrammation C# Un livre appartenant la srie Programmation et l'tagre Informatique de Wikilivres.

Ce livre prsente le langage C#. Il est destin ceux qui souhaitent utiliser ce langage de programmation orient objet, que le lecteur soit un programmeur dbutant ou confirm. Pour s'adresser un large public, tudiant ou professionnel, cet ouvrage est divis en plusieurs parties. Dans les premires parties prsentant les bases, il est conseill de suivre l'ordre des chapitres. La premire partie prsente le langage et les outils pour l'utiliser. Introduction Compilation Un premier programme

Le langageCette partie prsente la syntaxe de base du langage C#. Les commentaires Les espaces de noms Les variables et les constantes Les types de base et les dclarations Les tableaux Les objets Les classes Les fonctions Proprits et indexeurs Les oprateurs Les structures de contrle Hritage de classes Classe abstraite Les exceptions Structures et numrations Interfaces

Programmation avanceCette section s'adresse aux programmeurs avancs voulant exploiter les fonctionnalits les plus avances du langage. Type partiel Surcharge des oprateurs Directives du prprocesseur Documentation XML des classes Attributs Delegates et events Types gnriques Appel de plateforme Code non vrifi

Programmation C sharp

2

API .NetCette partie prsente les classes de l'API pour utiliser les fonctions du systme d'exploitation. Interfaces graphiques Graphique vectoriel Fonctions asynchrones Threads et synchronisation Processus Entres-sorties La srialisation Les fichiers Programmation rseau Excution distante

RessourcesCette section prsente une liste de ressources utiles pour en apprendre davantage sur le langage C#. Bibliographie et liens Index des mots-cls du langage Livre d'or

Programmation C sharp/IntroductionLe langage de programmation C# (C dise en franais, ou prononc C-sharp en anglais) a t dvelopp par la socit Microsoft, et notamment un de ses employs, Anders Hejlsberg, pour la plateforme .NET (point NET / dot NET). Ce langage est orient objet, avec un typage fort. Il est trs proche du langage Java. Il est prcompil en MSIL (Microsoft Intermediate Language), puis excut sur une machine virtuelle, ou compil en code natif l'excution. Il dispose d'un ramasse-miettes (garbage collector). Il utilise l'API .NET en remplacement des MFC (Microsoft foundation class). Il semble tre le nouveau langage pour dvelopper des applications Windows, avec Visual Basic et C++.C sharp

Caractristiques partagesLe langage C# possde un certain nombre de caractristiques communes avec d'autres langages de programmation. Il sera donc plus facile de l'apprendre si ces autres langages sont connus.

Caractristiques partages avec le langage Java Syntaxe : les mots cls communs avec Java s'utilisent dans les mmes circontances et de la mme manire : public, private, protected, abstract, class, interface, try, catch, finally, throw, new, return, this, if, while, do, for, foreach, enum... et le mot cl lock est l'quivalent C# du mot cl Java synchronized; Garbage collector : les objets qui ne sont plus rfrencs sont traits par le ramasse-miettes afin de librer la mmoire qu'ils occupent ; Rfrences : les objets sont en fait des rfrences ; Documentation automatique : cette caractristique commune utilise cependant une syntaxe diffrente dans les 2 langages : le langage Java utilise les commentaires spciaux /** */ au format HTML, avec des tags

Programmation C sharp/Introduction commenant par le caractre arobase @ ; tandis que le langage C# utilise les commentaires /// au format XML ; Mthodes courantes : une majeure partie des mthodes de l'API de C# ressemblent celles de Java, except que leur nom commence par une majuscule : Main, Equals, ToString, Length, IndexOf, ...

3

Caractristiques partages avec le langage C++ surcharge des oprateurs ; structures (mot cl struct) ; numrations (mot cl enum) ; pointeurs : il est possible, en mode unsafe, d'utiliser des pointeurs au lieu de rfrences.

Caractristiques propres au langage C# proprits : une proprit est un couple de mthodes (get et set) appeles lorsque celle-ci est lue ou modifie ; attributs : un attribut est li une dclaration et contient des mta-donnes sur celle-ci (mthode obsolte, importe d'une DLL, ...) ; delegate : un delegate est un modle de mthode, qui lorsqu'il est appel, appelle toutes les mthodes qui lui ont t associes. Pour faire un parallle avec le C++, les delegates peuvent tre compars des pointeurs de fonction. Leur smantique est toutefois nettement plus riche qu'en C++.

Programmation C sharp/CompilationLes fichiers sourcesUn fichier source C# porte l'extension ".cs". Il s'agit d'un fichier texte. Le programme compil porte l'extension ".exe". Une bibliothque rassemble des classes et porte l'extension ".dll". Elle peut tre utilise par un programme ou une autre bibliothque.

La compilationUn compilateur C# permet la traduction du programme source en instructions .Net. Contrairement d'autres compilateurs, ces instructions sont produites pour un processeur virtuel et ne sont donc pas directement interprtes par le processeur, mais interprts par le moteur .Net. Sous Windows, le compilateur produit un excutable appelant l'interprteur .Net. Sous Linux, le programme produit n'est pas directement excutable et doit tre lanc en argument de l'interprteur mono.

Programmation C sharp/Compilation

4

CompilateursPlusieurs compilateurs C# existent selon la plateforme utilise. Il existe plusieurs versions des spcifications du framework : 1.0, 1.1, 2.0. Ces versions successives ajoutent de nouvelles fonctionnalits au langage. Il existe galement diffrentes versions de la spcification du langage C# : C#1.0 : version initiale du langage, C#2.0 (version actuelle) : ajoute de nouvelles classes l'API (compression de donnes, collections gnriques, ...), permet l'utilisation de types gnriques, facilite la cration d'numration avec le mot cl yield, C#3.0 (future version) : ajoute de nouvelles facilits de syntaxe : types non spcifis pour les variables locales (dduit d'aprs la valeur d'initialisation), intgration des requtes SQL dans le langage (LINQ [1] ), ajout de nouvelles mthodes une classe existante, expressions lambda pour les delegates anonymes, initialisation des membres d'un objet la dclaration.

Compilateur pour WindowsSi le framework Microsoft .NET est install, le compilateur nomm csc.exe doit se situer dans C:\WINDOWS\Microsoft.NET\Framework\vnumro_de_version_du_framework. Le framework .NET est disponible gratuitement pour les utilisateurs de Windows. Il est galement possible d'utiliser Visual Studio .NET pour dvelopper, compiler et dbogguer les applications C#. L'dition Express de Visual Studio est tlchargeable gratuitement sur le site de Microsoft [2] , mais possde moins d'outils que la version complte. Une autre possibilit est d'utiliser SharpDevelop qui a l'avantage d'tre un logiciel libre [3] .

Compilateur pour LinuxMono est une implmentation libre de la plate-forme de dveloppement Microsoft .NET. Le compilateur est nomm msc. L'interprteur est nomm mono[4] . gmcs est le nouveau compilateur C# 2.0. Il est recommand d'utiliser ce dernier.

Rfrences[1] [2] [3] [4] http:/ / msdn. microsoft. com/ data/ ref/ linq/ http:/ / msdn. microsoft. com/ vstudio/ express/ visualcsharp http:/ / www. icsharpcode. net/ OpenSource/ SD/ http:/ / www. mono-project. com

Compilation et excutionLa compilation et l'excution peuvent se faire l'aide d'un environnement graphique. Il est toutefois utile de connatre la ligne de commande utiliser en cas d'absence d'environnement graphique ou si une option spciale de compilation doit tre utilise, ... Pour utiliser les lignes de commandes de compilation : 1. Ouvrir une fentre console, 2. Faire du rpertoire du programme compiler ou excuter le rpertoire courant, 3. Vrifier que la variable d'environnement PATH contient le chemin vers le compilateur, en tapant le nom du compilateur (csc sous Windows, gmcs sous Linux (Mono)). Si le compilateur ne se lance pas (programme non trouv) : Vrifier qu'un compilateur C# est install,

Programmation C sharp/Compilation Vrifier que le chemin complet du rpertoire du compilateur est contenu dans la variable d'environnement PATH, Essayer de lancer le compilateur en donnant son chemin complet. Le compilateur peut produire soit directement un excutable, soit un module (une bibliothque DLL) utilisable par d'autres programmes. Si les sources d'un excutable ou d'un module sont rpartis entre diffrents fichiers (mme rpertoire ou non), il faut spcifier leur chemin au compilateur. Exemple : Les sources de l'excutable prog.cs sont rpartis dans deux fichiers : C:\Prog\Exemple\main.cs et D:\Prog\Util\util.cs. Il faut donc utiliser la ligne de commande suivante :Windows csc C:\Prog\Exemple\main.cs D:\Prog\Util\util.cs

5

Linux (Mono) gmcs C:\Prog\Exemple\main.cs D:\Prog\Util\util.cs

Il est galement possible d'utiliser les caractres gnriques * et ? pour spcifier plusieurs fichiers. Les syntaxes des commandes utiliser pour les diffrentes tches du dveloppement sont rsumes dans le tableau suivant :Tche compiler un programme (.exe) avec fentre console compiler un programme (.exe) sans fentre console Windows csc fichier.cs Linux gmcs fichier.cs

csc /t:winexe fichier.cs

gmcs -target:winexe fichier.cs

compiler une bibliothque (.dll) csc /t:library fichier.cs gmcs -target:library fichier.cs utiliser une bibliothque (.dll) excuter un programme csc /r:fichier.dll ... programme arguments... gmcs -r:fichier.dll ... mono programme.exe arguments...

Programmation C sharp/Un premier programme

6

Programmation C sharp/Un premier programmeHello worldCet exemple typique de programmation est cens montrer la syntaxe du langage.

Le fichier sourceEnregistrez le listing suivant dans un document texte, intitul par exemple helloworld.cs : using System; public class HelloWorld { public static void Main() { Console.WriteLine("Hello world !"); Console.ReadLine(); } }

TestCompilez-le, puis lancer l'excutable produit. Le programme doit afficher : Hello world !

DtailsVoici le dtail ligne par ligne du fichier source, certains concepts tant expliqus dans les chapitres suivants : using System; Le fichier source utilise l'espace de noms nomm "System". public class HelloWorld { Dclaration d'une classe nomme "HelloWorld". public static void Main() { Dclaration d'une mthode statique nomme "Main" dans la classe HelloWorld. Cette mthode est celle qui est appele au dmarrage du programme. Console.WriteLine("Hello world !"); Affichage de la ligne "Hello world !" sur la console. Console dsignant la console, appartient l'espace de nom System. Console.ReadLine();

Programmation C sharp/Un premier programme Attendre que la touche entre soit frappe avant de poursuivre. Cette ligne de code n'est pas ncessaire si vous lancez le programme depuis une console dj ouverte. Dans le cas contraire (double-clic sous Windows), cette ligne de code permet de maintenir la fentre de console ouverte, car celle-ci se ferme une fois le programme termin (option par dfaut). }

7

Fin de la mthode Main. }

Fin de la classe HelloWorld.

Hello world en bibliothqueLe programme de cet exemple a le mme but que le prcdent : afficher le message "Hello world !" sur la console. Cette version utilisera une seconde classe compile en bibliothque.

Les fichiers sourcesEnregistrez ce premier listing dans un document texte, intitul par exemple helloworld.cs : using System; public class HelloWorld { public static void Afficher() { Console.WriteLine("Hello world !"); Console.ReadLine(); } } Enregistrez le second listing dans un document texte, intitul par exemple premierprog.cs : public class PremierProg { public static void Main() { // appel la mthode statique Afficher() de la classe HelloWorld HelloWorld.Afficher(); } }

Programmation C sharp/Un premier programme

8

TestCompilez la bibliothque :Windows csc /t:library helloworld.cs

Linux (Mono) gmcs -target:library helloworld.cs

Le compilateur a cr un fichier nomm helloworld.dll. Cette bibliothque doit tre utilise lors de la compilation du programme principal. Compilez le programme :Windows csc /r:helloworld.dll premierprog.cs

Linux (Mono) gmcs -r:helloworld.dll premierprog.cs

Le compilateur a produit un fichier nomm premierprog.exe. Puis lancez l'excutable produit :Windows premierprog.exe

Linux (Mono) mono premierprog.exe

Le programme doit afficher : Hello world !

9

Le langageProgrammation C sharp/Les commentairesTout bon programme a des fichiers sources bien comments pour expliquer comment cela fonctionne et pourquoi certains choix ont t faits. Ce qui vite une perte de temps lorsque le code source est repris et modifi, soit par un autre dveloppeur, soit par l'auteur qui ne se souvient pas forcment de son projet s'il n'y a pas touch depuis longtemps.

Bloc de commentaireUn bloc de commentaire est dlimit par les signes slash-toile /* et toile-slash */ comme en Java et en C++. Exemple : /* Un commentaire explicatif sur plusieurs lignes... */ Les blocs ne peuvent tre imbriqus car ds que le compilateur trouve slash-toile /*, il recherche la premire occurrence d'toile-slash */ terminant le commentaire. /* : dbut du commentaire /* : ignor fin du commentaire : */ erreur ici car le commentaire est fini : */

Commentaire de fin de ligneUn commentaire de fin de ligne dbute par un double slash // et se termine au prochain retour la ligne. Exemple : x++; // augmenter x de 1

Astuce : Visual Studio utilise ce type de commentaire pour les commandes commenter/dcommenter le groupe de lignes slectionnes (raccourcis claviers : [Ctrl-E] [C] pour commenter, [Ctrl-E] [U] pour dcommenter, ou [Ctrl-K] [C] et [Ctrl-K] [U] avec les versions de Visual Studio .NET antrieures 2005).

Programmation C sharp/Les commentaires

10

Commentaire de documentationLe langage C# utilise une forme spciale des commentaires pour documenter les classes. Ces commentaires commencent par un triple slash /// et se terminent au prochain retour la ligne. Alternativement, ils peuvent tre encadrs par /** et */. Le contenu de ces commentaires est au format XML. Il est possible d'utiliser plusieurs lignes. Cette documentation se rapporte toujours un des lments de la dclaration qui suit. Exemple : /// /// Une classe pour dmontrer /// les commentaires de documentation /// public class Exemple { ... } Certaines balises XML sont standards, mais il est possible d'utiliser des balises supplmentaires. Pour plus de dtails, voir le chapitre nomm Documentation XML des classes.

Programmation C sharp/Les espaces de nomsDfinitionUn espace de nom regroupe plusieurs dclarations sous un mme nom ajout ceux des lments dclars (classes, interfaces, espace de nom imbriqu). Exemple : namespace MesClasses { public class ClasseUne { ... } public class ClasseDeux { ... } }

Programmation C sharp/Les espaces de noms

11

Utiliser les membres d'un espace de nomLes classes dfinies l'intrieur de cet espace de noms peuvent se faire rfrence par leur nom simple : ClasseUne, ClasseDeux. Une classe membre d'un autre espace de nom ou d'aucun doit forcment utiliser le nom absolu des classes, c'est dire : MesClasses.ClasseUne, MesClasses.ClasseDeux ou bien utiliser la directive using : using namespace; Exemple : using MesClasses; public class ClasseTest { ClasseUne objet1; ClasseDeux objet2; } quivaut : public class ClasseTest { MesClasses.ClasseUne objet1; MesClasses.ClasseDeux objet2; } L'exemple du chapitre "Un premier programme" utilise dj un espace de nom : la classe Console est dfinie dans l'espace de noms System.

Imbrication des espaces de nomsL'imbrication des espaces de noms est possible : namespace MesClasses { namespace Calcul { ... // espace de nom } } Ou directement : namespace MesClasses.Calcul { ... // espace de nom MesClasses.Calcul }

MesClasses.Calcul

Programmation C sharp/Les espaces de noms

12

Espace de noms en plusieurs partiesPlusieurs fichiers sources peuvent contribuer ajouter des dclarations un mme espace de noms. Exemple : Fichier : images.cs using System; namespace Exemple.Images { public class Image { ... } public class ImageBitmap : Image { ... } ... } Fichier : couleurs.cs using System; namespace Exemple.Couleurs { public class Couleur { ... } public class ConversionCouleur { ... } ... }

Alias d'espace de nomLe mot cl using peut servir assigner un autre nom (plus court en gnral) un espace de nom. Exemple : using coll = System.Collections; public class Exemple { coll::Hashtable donnees = new coll::Hashtable(); } Crer un alias d'espace de nom est galement utile pour utiliser deux classes portant le mme nom, situes dans deux espaces de nom diffrents. Exemple : namespace Gestion.Transport { public class Ligne { ... } } namespace Graphique.Dessin { public class Ligne { ... } }

Programmation C sharp/Les espaces de noms Si l'instruction using est utilise deux fois, le nom Ligne est ambigu, comme l'explique l'erreur produite par le compilateur : using Gestion.Transport; using Graphique.Dessin; public class Exemple { Ligne exemple; // -> error CS0104: 'Ligne' is an ambiguous reference between // 'Gestion.Transport.Ligne' and 'Graphique.Dessin.Ligne'. } Dans ce cas, on peut utiliser l'instruction using pour l'un des deux espaces de nom et utiliser le nom complet pour l'autre espace de nom : using Gestion.Transport; public class Exemple { Ligne transport; Graphique.Dessin.Ligne trace; } Il est galement possible de dfinir deux alias d'espace de nom afin d'abrger les rfrences: using transport=Gestion.Transport; using dessin=Graphique.Dessin; public class Exemple { transport::Ligne transport; dessin::Ligne trace; }

13

Conflit de nomIl est possible que le code source utilise des noms dj utilis comme espace de noms. Dans l'exemple de code suivant, les noms System et Console font rfrence des attributs de la classe Classe. public class Classe { private string System = "system"; private string Console = "console"; public void Afficher() { // System.Console.WriteLine("Exemple"); // provoque une erreur } }

Programmation C sharp/Les espaces de noms Il est toutefois possible d'utiliser System.Console en utilisant le prfixe global:: qui permet de spcifier que l'on accde l'espace de nom racine de tous les autres (implicite par dfaut) : public class Classe { private string System = "system"; private string Console = "console"; public void Afficher() { global::System.Console.WriteLine("Exemple"); // OK } }

14

Alias d'assemblagesLorsqu'une application utilise des assemblages dont les noms de classes complets (espace de nom inclus) sont identiques (deux versions/implmentations d'une mme classe), l'ambigut doit tre rsolue en utilisant des alias d'assemblages. Pour utiliser deux versions d'une mme classe dfinies dans les assemblages grid.dll (version 1.0, alias "GridV1") et grid20.dll (version 2.0, alias "GridV2"), il faut dfinir les alias utiliser dans la ligne de commande de compilation :Windows csc /r:GridV1=grid.dll /r:GridV2=grid20.dll ...

Linux (Mono) gmsc -r:GridV1=grid.dll -r:GridV2=grid20.dll ...

Cela cre les alias externes GridV1 et GridV2. Pour utiliser ces alias partir d'un programme, il faut les rfrencer l'aide du mot cl extern : extern alias GridV1; extern alias GridV2; Ces deux instructions crent deux nouvelles racines d'espace de nom en plus de global : extern alias GridV1; extern alias GridV2; public class Exemple { GridV1::Grid grid_v1; // implmentation V1.0 (grid.dll) GridV2::Grid grid_v2; // implmentation V2.0 (grid20.dll) }

Programmation C sharp/Les variables et les constantes

15

Programmation C sharp/Les variables et les constantesLes variablesUne variable rserve une place en mmoire pour stocker des donnes : rsultats d'expressions, donnes lues depuis un fichier, ... Elle est associe un nom.

DclarationUne variable possde un nom et un type. Ce type dtermine ce que peut stocker la variable : un nombre, une chane de caractre, un objet d'une classe particulire ... La syntaxe est la suivante : type nom [ = expression ] ; Exemples : double prix_unitaire; int quantite = 50; string article = "Pommes"; bool rabais = false; Assigner une variable (initialiser) la dclaration n'est pas obligatoire. Dans ce cas, elle possde la valeur par dfaut correspondant au type : la valeur par dfaut des types numriques et caractres (char) est zro (0), la valeur par dfaut du type boolen (bool) est false, la valeur par dfaut des types rfrences (objet, chane de caractre, tableaux) est null, la valeur par dfaut des types numrs (enum) est celle qui correspond au type sous-jacent (int par dfaut).

Il est possible de regrouper la dclaration de plusieurs variables du mme type en utilisant une virgule pour sparer les diffrentes variables. Exemple : int quantite = 50, nombre, quantite_en_stock = 100 ; Ou en plaant une variable par ligne pour plus de clart : int quantite = 50, nombre, quantite_en_stock = 100 ;

Programmation C sharp/Les variables et les constantes

16

UtilisationUne variable est utilise pour stocker des rsultats intermdiaires, des donnes qui serviront ultrieurement. La valeur d'une variable peut tre modifie autant de fois que ncessaire. Exemple : prix_unitaire = 1.50; if (rabais) prix_unitaire = prix_unitaire - 0.20; double prix_total = prix_unitaire * quantite ;

Porte d'une variableLa porte d'une variable est l'ensemble des emplacements dans le code o cette variable est accessible. En dehors de cette porte, l'utilisation du mme nom correspondra une autre variable ou plus souvent aucune variable (erreur de compilation dans ce cas). La porte d'une variable correspond au bloc d'accolades o elle est dclare. Une variable membre d'une classe est dclare au niveau de la classe et est accessible depuis les autres membres de la classe (mthodes, indexeurs, proprits, ...). Une variable locale est dclare l'intrieur d'un bloc d'accolades (celui de la mthode/proprit membre, ou un bloc interne celle-ci). Exemple : public class Exemple { // variable membre de la classe : int nombre = 5; // porte : la classe Exemple public int MethodeUne() { // variable locale la mthode : int nombre = 10; // porte : la mthode MethodeUne() return nombre + // la variable locale this.nombre; // la variable membre // retourne 10 + 5 , c'est dire 15 } public int MethodeDeux() { System.Console.WriteLine("Nombre = " + nombre); // la variable membre // Nombre = 5 { int nombre = 20; // variable locale au bloc d'accolades System.Console.WriteLine("Nombre = " + nombre); // la variable locale // Nombre = 20 } // la variable locale est hors de porte

Programmation C sharp/Les variables et les constantes System.Console.WriteLine("Nombre = " + nombre); // la variable membre // Nombre = 5 } }

17

Dure de vie d'une variableLa dure de vie d'une variable est la priode durant laquelle une variable existe, c'est dire conserve son emplacement en mmoire et durant laquelle elle peut donc stocker des donnes.

Variable en lecture seuleUne variable peut tre dclare en lecture seule en utilisant le mot-cl readonly. Exemple : readonly double taux_tva = 19.6; Il n'est pas obligatoire d'initialiser une variable en lecture seule lors de sa dclaration. Ce qui permet de dterminer la valeur en fonction d'autres donnes, ou de lire sa valeur depuis un fichier par exemple, et d'empcher sa modification aprs affectation. Exemple : class Facture { public readonly double taux_tva; public Facture(bool taux1) { if (taux1) taux_tva = 19.6; else taux_tva = 5.5; } }

Les constantesUne constante nomme est associe une valeur pour toute la dure de l'application. Sa valeur ne peut changer.

DclarationLa syntaxe est similaire celle de la dclaration d'une variable, except que le mot cl const prcde la dclaration, et que l'initialisation la dclaration est obligatoire : const type nom = expression ; Exemple : const double prix_unitaire_unique = 1.50 ; const double taux_euro_en_francs = 6.55957 ; Comme les variables il est galement possible de regrouper la dclaration de plusieurs constantes du mme type : const double prix_unitaire_unique = 1.50 , taux_euro_en_francs = 6.55957 ;

Programmation C sharp/Les variables et les constantes N.B.: Une constante est implicitement statique. Il est donc inutile d'ajouter le mot-cl static, sinon le compilateur gnre une erreur.

18

Types des constantesLe mot const ne s'applique qu'aux types standards numriques, boolens, string, et numrations.

Porte et dure de vie d'une constanteLes mmes rgles que celles pour les variables s'appliquent galement aux constantes.

Programmation C sharp/Les types de base et les dclarationsEn C#, il existe deux catgories de type : Les types valeurs qui stockent directement la valeur des donnes (un entier, une chane de caractres, une structure), Les types rfrences qui stockent une rfrence vers la valeur des donnes (un tableau, un objet, une interface). Les variables de ce type se distinguent par le fait qu'elles valent initialement null et qu'il faut explicitement leur allouer de l'espace mmoire avec new. Les donnes rfrences par ces variables sont donc soumises au garbage collector quand plus aucune rfrence n'existe, afin de librer la place mmoire occupe. Un type de base est un type simple valeur.

Liste des types de baseType bool char sbyte byte short ushort int uint long ulong float double Classe System.Bool System.Char System.SByte System.Byte System.Int16 System.UInt16 System.Int32 System.UInt32 System.Int64 System.UInt64 System.Single System.Double Description Boolen (vrai ou faux : true ou false) true Caractre Unicode (16 bits) Entier sign sur 8 bits (1 octet) Entier non sign sur 8 bits (1 octet) Entier sign sur 16 bits Entier non sign sur 16 bits Entier sign sur 32 bits Entier non sign sur 32 bits Entier sign sur 64 bits Entier non sign sur 64 bits Nombre virgule flottante sur 32 bits Nombre virgule flottante sur 64 bits 'A' -128 255 -129 1450 -100000 8000000 -2565018947302L 8000000000000L 3.14F 3.14159 3.1415926M "Exemple" "C:\\windows\\system32" @"C:\windows\system32" Exemples

decimal System.Decimal Nombre virgule flottante sur 128 bits string System.String Chane de caractres

Programmation C sharp/Les types de base et les dclarations

19

Syntaxe des chanes de caractresComme illustr par l'exemple du tableau ci-dessus, une chane de caractres peut avoir deux syntaxes diffrentes : Syntaxe avec caractres d'chappement : La chane est entoure par les guillemets et l'anti-slash introduit un caractre spcial (\n, \t ...) ou empche son interprtation (guillemet \" et anti-slash \\) Syntaxe verbatim : La chane est prcde d'un caractre arobase, et l'anti-slash n'est pas interprt. Si un guillemet doit faire partie de la chane de caractre, il faut le doubler "". Exemples : "un guillemet \", un anti-slash \\, un retour la ligne\n" @"un guillemet "", un anti-slash \, un retour la ligne " La syntaxe verbatim simplifie la frappe des chemins de fichiers qui utilisent le caractre anti-slash comme sparateur : @"C:\program files\monapp\monfichier.txt"

Auto-boxing/unboxingChaque type de donnes correspond une classe de l'espace de nom System. La conversion entre le type et une instance de cette classe est implicite et invisible. Ainsi, on peut appeler des mthodes sur les types simples, affecter une constante o une classe de type est attendue (et vice versa), ... Exemple : int a = 25; string message = 36.ToString(); // convertit 36 en chane de caractres, // mthode dfinie dans la classe System.Int32 UInt32 b = 50;

Types nullableLe langage C#2.0 introduit la possibilit pour les types simples de valoir null. Cette fonctionnalit permet une meilleure interoprabilit avec les bases de donnes qui utilisent ce type de donnes. Pour qu'une variable puisse valoir null (nullable), il faut que le type soit suivi d'un point d'interrogation. Par exemple : int? numero = null; Il est donc possible de tester qu'une variable de ce type vaut null : if (numero==null) numero = 50; else numero++; Le nouvel oprateur ?? (double point d'interrogation) permet de slectionner l'oprande de gauche s'il ne vaut pas null, ou l'oprande de droite sinon : valeur_ou_null??valeur_si_null Cet oprateur est donc pratique utiliser avec les types nullables pour obtenir une valeur par dfaut :

Programmation C sharp/Les types de base et les dclarations Console.WriteLine("Numro : "+( numero??50 ));

20

Valeur par dfautL'oprateur default retourne la valeur par dfaut du type spcifi. Il s'agit de la valeur quand une variable de ce type n'est pas initialise (0 pour les nombres, null pour les types rfrences). Exemple: public int absolu(int? valeur) { if (valeur==null) return default(int); else return (valeur= b

Les oprateurs boolensUne expression boolenne (telle les comparaisons) sont des conditions qui peuvent tre combines avec les oprateurs suivants : L'oprateur non retourne le contraire de l'oprande (vrai pour faux, et faux pour vrai). Exemple : !(a==5) L'oprateur et ne retourne vrai que si les deux oprandes sont vrais. Exemple : (a==5) && (b==0) L'oprateur ou retourne vrai si l'un des deux oprandes est vrai. Exemple : (a==5) || (b==0) L'oprateur ou exclusif retourne vrai si un seul des deux oprandes est vrai, c'est dire qu'il retourne vrai pour les couples d'oprandes (vrai, faux) et (faux, vrai). Comme dans de nombreux langages, il n'existe pas d'oprateur ou-exclusif spcifique. Mais on peut utiliser l'oprateur de comparaison diffrent pour comparer les valeurs boolennes (false/true). Exemple : (a==5) != (b==0)

Les oprateurs de manipulation des bitsLes exemples montrent la reprsentation binaire des oprandes de type octet (byte), donc sur 8 bits. Les oprateurs suivants manipulent les bits : L'oprateur non retourne l'inverse des bits de l'oprande (0 pour 1, et 1 pour 0). Exemple : ~ 0x93 ~ 1001 0011 = 0110 1100 (0x93) (0x6C)

L'oprateur et ne retourne que les bits 1 communs aux deux oprandes. Exemple : 0x93 & 0x36 1001 0011 & 0011 0110 = 0001 0010 (0x93) (0x36) (0x12)

L'oprateur ou retourne les bits 0 communs aux deux oprandes. Exemple : 0x93 | 0x36 1001 0011 | 0011 0110 = 1011 0111 (0x93) (0x36) (0xB7)

L'oprateur de dcalage de bits vers la gauche, comme son nom l'indique, dcale les bits de l'oprande vers la gauche, du nombre de bits spcifi par le second oprande. Les bits les plus gauche sont donc perdus. Exemple : 0x93 Description Qualificateur d'alias d'espace de noms Parenthses pour valuer en priorit Tableau Slection d'un membre par un identificateur (structures et objets) Slection d'un membre par un pointeur (structures et objets) Incrmentation post ou pr-fixe Oprateur moins unaire (change le signe de l'oprande) Non logique et Non binaire Conversion de type Drfrencement Rfrencement (adresse d'une variable) Conversion de type rfrence (pas d'exception lance) Test de type Type d'une variable / expression Taille d'une variable / d'un type Allocation mmoire de droite gauche Associativit de gauche droite

++ -+ ! ~ (type) * & as is typeof sizeof new

Programmation C sharp/Les oprateurs

40de gauche droite

*/% +> < >= == != & ^ | && || c?t:f = += -= *= /= %= = &= ^= |= ,

Multiplication, division, et modulo (reste d'une division) Addition et soustraction Dcalage de bits vers la droite ou vers la gauche Comparaison infrieur strictement et infrieur ou gal Comparaison suprieur strictement et suprieur ou gal Condition gal et diffrent ET binaire OU exclusif binaire / logique OU binaire ET logique boolen OU logique boolen Oprateur ternaire de condition Affectation Affectation avec somme ou soustraction Affectation avec multiplication, division ou modulo Affectation avec dcalage de bits Affectation avec ET, OU ou OU exclusif binaires Squence d'expressions

de droite gauche

de gauche droite

Erreurs dans les expressionsDiffrents types d'erreur peuvent survenir dans une expression : division par zro : le rsultat est indfini, dbordement du rsultat : le nombre de bits du type accueillant le rsultat est insuffisant. Si l'expression o se situe l'erreur est constante (pas de variable dans l'expression), le rsultat est valu la compilation, et produit en cas d'erreur une erreur de compilation. Si au contraire, l'expression n'est pas constante, une erreur provoque le lancement d'une exception. Ce comportement peut tre modifi pour le dbordement par les mots-cls checked et unchecked.

Vrification du dbordementLe dbordement provoque une exception System.OverflowException. checked( expression ) Il s'agit du contexte par dfaut pour les expressions constantes, c'est dire celles qui peuvent tre values lors de la compilation.

Non vrification du dbordementLe dbordement provoque une copie partielle (les bits de poids faibles) du rsultat de l'expression. unchecked( expression ) Il s'agit du contexte par dfaut pour les expressions non constantes, c'est dire celles qui ne peuvent tre values que lors de l'excution.

Programmation C sharp/Structures de contrle

41

Programmation C sharp/Structures de contrleLe language C# est un langage de programmation structur. La structure d'un programme dfinit l'ordre d'excution des instructions : condition, boucles, ...

ConditionUne instruction peut s'excuter lorsqu'une condition est vraie. La syntaxe est la suivante : if (expression) instruction expression dfinit la condition et doit tre du type bool, c'est dire qu'elle ne peut valoir que true (vrai) ou false (faux). L'instruction n'est excute que si la condition est vraie (true). Exemple : if (a==10) Console.WriteLine("a vaut 10");

Plusieurs instructionsPour excuter plusieurs instructions si la condition est vraie, instruction peut tre remplac par un bloc d'instructions entre accolades : { instruction instruction ... } Exemple : if (a==10) { Console.WriteLine("a vaut 10"); a=9; Console.WriteLine("dsormais a vaut 9"); }

Sinon...Il est possible d'excuter des instructions quand une condition est vraie, et d'autres instructions quand elle est fausse. La syntaxe est la suivante : if (expression) instruction else instruction Exemples : if (a==10) Console.WriteLine("a vaut 10"); else Console.WriteLine("a ne vaut pas 10");

Programmation C sharp/Structures de contrle if ((a==10)&&(b==11)) Console.WriteLine("a vaut 10 et b vaut 11"); else Console.WriteLine("a ne vaut pas 10 ou b ne vaut pas 11");

42

Conditions multiplesL'enchanement des instructions conditionnelles est possible. Exemple : if (a==10) if (b==11) Console.WriteLine("a vaut 10 et b vaut 11"); else Console.WriteLine("a vaut 10 mais b ne vaut pas 11"); else Console.WriteLine("a ne vaut pas 10"); Chaque instruction else correspond au if qui le prcde, s'il n'a pas dj de else. Cependant, pour clarifier le code ou rsoudre certains cas ambigus (pas de else pour le second if, par exemple), il est prfrable de mettre des accolades : if (a==10) { if (b==11) Console.WriteLine("a vaut 10 et b vaut 11"); else Console.WriteLine("a vaut 10 mais b ne vaut pas 11"); } else Console.WriteLine("a ne vaut pas 10"); Autre exemple : if (a==10) Console.WriteLine("a vaut 10"); else if (a==11) Console.WriteLine("a vaut 11"); else Console.WriteLine("a ne vaut ni 10, ni 11"); Dans cet exemple, chaque instruction if n'est teste que si la prcdente est fausse. Si le nombre de cas est important et que chaque condition teste une valeur pour la mme expression, il est prfrable d'utiliser l'instruction switch.

Tests de plusieurs casL'instruction switch permet de tester la valeur d'une expression avec plusieurs cas. La syntaxe est la suivante : switch(expression) { cas : cas : ... instructions fin du cas cas : cas : ... instructions fin du cas

Programmation C sharp/Structures de contrle

43

... } O cas peut avoir l'une des deux syntaxes suivantes : case constante Cas o l'expression vaut la constante spcifie. default Cas o l'expression ne correspond aucun autre cas (le cas par dfaut). fin du cas est une instruction spciale terminant le ou les cas. Hormis les instructions interrompant le cours de l'excution (une instruction interrompant ou continuant une boucle, une instruction throw pour lancer une exception, une instruction return), il s'agit en gnral de l'une des deux instructions suivantes : break; Fin du test, la prochaine instruction excute est celle situe aprs l'accolade fermante de switch. goto cas; L'excution se poursuit au cas indiqu. Exemple : switch(a) { case 10 : Console.WriteLine("a vaut 10"); break; case 11 : Console.WriteLine("a vaut 11"); break; default : Console.WriteLine("a ne vaut ni 10, ni 11"); break; } La syntaxe permet de rassembler plusieurs cas ensembles pour excuter les mmes instructions : switch(a) { case 2 : case 3 : case 5 : Console.WriteLine("a vaut 2, 3 ou 5"); break; case 10 : case 11 : Console.WriteLine("a vaut 10 ou 11"); break;

Programmation C sharp/Structures de contrle

44

default : Console.WriteLine("a n'est pas dans la liste (2, 3, 5, 10, 11)"); break; } Il est galement possible de poursuivre le traitement avec les instructions d'un autre cas : switch(a) { case 10 : Console.WriteLine("a vaut 10"); goto case 11; case 11 : Console.WriteLine("a vaut "+a); break; default : Console.WriteLine("a ne vaut ni 10, ni 11"); break; }

BouclesUne boucle permet d'excuter plusieurs fois une ou des instructions tant qu'une condition est vraie.

Boucle whileLa boucle while est la plus simple : tant que la condition est vraie, elle excute l'instruction ou le bloc d'instructions spcifi. Sa syntaxe est la suivante : while ( expression ) instruction_ou_bloc O expression est une expression du type bool, c'est dire valant true (vrai) ou false (faux). Exemple : rechercher une valeur spcifique dans un tableau d'entiers int i = 0; // tant que i est un indice correct et que la valeur 0 n'est pas trouve while ( (i < tableau.Length ) && ( tableau[i] != 0 ) ) { Console.WriteLine(tableau[i]); i++; } N.B.: Si la condition est fausse ds le dbut, l'instruction ou le bloc n'est pas excut, car la condition est teste avant.

Programmation C sharp/Structures de contrle

45

Boucle do...whileLa boucle do...while ressemble la prcdente, except que la condition est teste aprs. C'est dire que le bloc d'instructions est toujours excut au moins une fois. La syntaxe est la suivante : do { instructions } while ( expression ); O expression est une expression de type bool. Exemple : string fichier; do { Console.Write("Entrez un nom de fichier ou rien pour quitter : "); fichier=Console.ReadLine(); if (fichier != "") TraiterFichier(fichier); } while ( fichier != "" );

Boucle forLa boucle for regroupe plusieurs phases de la boucle : L'initialisation, par exemple un indice dans un tableau, La condition, tant qu'elle est vraie la boucle continue, Les instructions excuter, L'instruction (ou les instructions) d'incrmentation, excute(s) juste avant de tester nouveau la condition.

La syntaxe d'une boucle for est la suivante : for ( initialisation ; condition ; incrmentation ) instructions Exemple : recherche d'une valeur nulle dans un tableau d'entiers for ( int i=0 ; (i placs juste aprs le nom de la mthode ou la classe.

Exemple de mthodeSoit une mthode statique retournant la valeur maximale entre deux valeurs passes en paramtre : public static T max(T a, T b) // Retourne la valeur maximale { return a > b ? a : b ; } int entier = max ( 10 , 22 ); double vmax = max ( 3.14 , 1.618 ); Le compilateur dtermine le type utilis pour T d'aprs les valeurs des arguments. Dans le cas prcdent, il gnre deux versions de la fonction : public static int max(int a, int b) public static double max(double a, double b)

Exemple de classeLa syntaxe est similaire. Soit une classe grant une structure en arbre de type quelconques : public class Arbre { public T valeur; private Arbre _gauche, _droite; public Arbre ArbreGauche { get { return _gauche; } } } L'utilisation de cette classe exige de spcifier explicitement le type utilis : Arbre ArbreDesEntiers = new Arbre(); ArbreDesEntiers.valeur = 100;

Programmation C sharp/Types gnriques

90

Exemple de structureLes types gnriques sont galement utilisables avec les structures : public struct Taille { public T largeur, hauteur; }

Plusieurs types gnriquesIl est possible d'utiliser plusieurs types gnriques pour une mthode ou une classe : public static void affiche(T a, U b) // Affiche a et b { Console.WriteLine("A vaut {0}, et B vaut {1}", a, b); } affiche(10,3.1415926);

Contraintes sur les types gnriquesIl est possible de restreindre les types utilisables ceux qui implmentent une ou plusieurs interfaces.

SyntaxePour chaque type contraindre, il faut ajouter une clause where : where type : liste_des_interfaces Exemple : public class TableauTriable where T : IComparable { //... } Il est possible d'utiliser class ou struct pour limiter le type une classe ou une structure. Exemple : public class TableauTriable where T : struct { //... } Il est galement possible d'ajouter des contraintes sur les constructeurs du type gnrique : public class TableauTriable where T : new() // T doit avoir un constructeur sans paramtre { public T Creer() {

Programmation C sharp/Types gnriques return new T(); // appel au constructeur de T } }

91

Oprateur defaultL'oprateur default retourne la valeur par dfaut du type gnrique spcifi. Il s'agit de la valeur quand une variable de ce type n'est pas initialise (0 pour les nombres, null pour les types rfrences). Exemple: public T maxAbsolu(T a,T b) { if (a==b) return default(T); else return a>b ? a : b; }

AliasIl est possible de dfinir un alias d'une classe gnrique spcifique, en utilisant le mot cl using : using Entiers = TableauTriable; Entiers entiers = new Entiers(); Equivaut : TableauTriable entiers = new TableauTriable();

Programmation C sharp/Appel de plateforme

92

Programmation C sharp/Appel de plateformeL'appel de plateforme permet au code gr (managed code) de faire appel du code non gr (unmanaged code) contenu dans une bibliothque externe, utilisant du code natif la plateforme.

SyntaxeLa mthode externe doit tre dclare comme statique (mot cl static) et externe (mot cl extern) ce qui signifie qu'il ne faut aucun bloc de code. Cette mthode doit obligatoirement utiliser l'attribut DllImport de l'espace de nom System.Runtime.InteropServices afin de dclarer le nom de la DLL utilise et d'autres paramtres optionnels permettant l'interoprabilit avec l'application .Net. Il est conseill de dclarer ces mthodes externes dans une classe spare.

Exempleusing System.Runtime.InteropServices; public class Win32 { [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern IntPtr MessageBox (int hWnd, String text, String caption, uint type); } public class HelloWorld { public static void Main() { Win32.MessageBox (0, "Hello World", "Platform Invoke Sample", 0); } }

En savoir plus Prsentation dtaille de l'appel de plate-forme [1]

Rfrences[1] http:/ / msdn2. microsoft. com/ fr-fr/ library/ 0h9e9t7d(VS. 80). aspx

Programmation C sharp/Code non vrifi

93

Programmation C sharp/Code non vrifiLe code produit par la compilation d'un programme C# est gr par l'environnement .Net qui effectue diverses vrifications, gre la mmoire en utilisant un ramasse-miette et peut lancer des exceptions en cas d'erreur : rfrence nulle, divisions par zro, variable non initialise, indexation d'un tableau au del de ses limites.Le langage C# permet d'utiliser du code non vrifi pour utiliser des pointeurs et d'autres fonctionnalits non scurises. Ce mode de fonctionnement est donc utiliser avec prcautions, et viter pour les dveloppeurs dbutants.

Le recours du code non vrifi peut tre ncessaire pour utiliser le systme d'exploitation, un priphrique accd par adresse mmoire, ... Le code non vrifi doit obligatoirement tre marqu avec le mot-cl unsafe. Ce qui permet d'empcher son excution dans un contexte non sr (code provenant d'une source non fiable).

DclarationLe mot-cl unsafe peut tre ajout la dclaration d'une mthode comme dans l'exemple suivant : public unsafe void Methode() { int iData = 10; int* pData = &iData; Console.WriteLine("Data contient " + *pData); Console.WriteLine("Son addresse est " + (int)pData ); } Il est galement possible de l'ajouter pour un bloc d'instruction seul : public void Methode() { int iData = 10; unsafe { int* pData = &iData; Console.WriteLine("Data contient " + *pData); Console.WriteLine("Son addresse est " + (int)pData ); } }

Programmation C sharp/Code non vrifi

94

PointeursUn pointeur est un type qui stocke une adresse vers une donne du type spcifi par le pointeur. La syntaxe d'utilisation est la mme que dans les langages C et C++.

DclarationLa dclaration d'un pointeur utilise un type suivi du caractre toile. Exemple : int* pEntier; // Pointeur d'entier

Adresse d'une variableUn pointeur peut recevoir l'adresse d'une variable, en faisant prcder la variable du caractre &. Exemple : int total; pEntier = &total; // adresse de la variable total

Drfrencer un pointeurUn pointeur utilis directement donnera l'adresse de la variable. Pour utiliser le contenu point par le pointeur il faut le drfrencer en le faisant prcder du caractre toile *. Exemple : *pEntier = 100; // modification de la variable total

Membre d'une classe pointePour accder un membre d'un objet point il est possible d'utiliser la syntaxe suivante : (*pEntier).ToString(); // accs la mthode ToString de l'entier point Ou d'utiliser l'oprateur flche quivalent : pEntier->ToString(); // accs la mthode ToString de l'entier point

Pointeur et tableauL'adresse d'un tableau est donne sans utiliser l'oprateur d'adresse &. Toutefois, il n'est pas possible de modifier l'adresse du tableau afin d'viter de perdre l'adresse de dbut du tableau. Le pointeur doit utiliser le mot-cl fixed pour obtenir l'adresse d'un tableau. Exemple : int[] valeurs = new int[10]; fixed (int* pEntier = valeurs) for (int iIndex = 0; iIndex < 10; iIndex++) Console.WriteLine( *(pEntier + iIndex) );

Programmation C sharp/Code non vrifi

95

Gestion de la mmoireLe mode non vrifi permet de modifier le comportement du ramasse-miettes.

viter le dplacement par le ramasse-miettesLe mot cl fixed sert viter qu'un tableau ou un objet ne soit dplac en mmoire par le ramasse-miettes : pour empcher le dplacement durant l'excution d'une instruction ou un bloc d'instructions : fixed (type* pointeur = adresse) instruction pour dclarer un tableau de taille fixe (non dplac en mmoire) : fixed type[nombre] variable; Exemple : protected fixed int[12] jours_par_mois;

Taille d'une variable ou d'un typeL'oprateur sizeof s'utilise dans un contexte de code non vrifi, comme une fonction renvoyant le nombre d'octets occups par la variable ou le type spcifi. Exemple : int a; unsafe { System.out.println("Taille de a : "+ sizeof(a) +" octets"); System.out.println("Taille d'un entier : "+ sizeof(int) +" octets"); }

Allocation sur la pileLe mot-cl stackalloc permet d'allouer un objet ou un tableau sur la pile plutt que sur le tas. Dans ce cas, cet objet ou tableau n'est pas gr par le ramasse-miettes. Il est donc possible d'utiliser un pointeur sans utiliser le mot-cl fixed. Syntaxe : le mot-cl stackalloc s'utilise la place du mot-cl new pour initialiser des pointeurs locaux. Exemple : unsafe { // allouer 10 entiers sur la pile int* pEntier = stackalloc int[10]; ... }

96

API .NetProgrammation C sharp/Interfaces graphiquesLes applications de la plateforme .Net construisent leur interface graphique partir de forms.

Espaces de nomLes deux principaux espaces de nom de l'interface graphique sont : System.Windows.Forms Cet espace de nom contient les classes correspondant aux divers composants de l'interface graphique (fentre, bouton, label, ...). System.Drawing Cet espace de nom gre le dessin dans un composant (ligne, rectangle, texte, image, ...).

CompilationSi l'application possdant une interface graphique n'a pas besoin de console, il est possible de la supprimer en spcifiant winexe pour le paramtre target dans la ligne de commande du compilateur :Windows csc /t:winexe fichier.cs

Linux (Mono) gmsc -target:winexe fichier.cs

Une premire fentreLa fentre est gre par la classe Form de l'espace de nom System.Windows.Forms. En gnral, l'application drive de cette classe pour ajouter des attributs de type composants, et grer les vnements. Cette premire fentre comportera un label Hello world ! et un bouton Fermer . Source : using System; using System.Windows.Forms; using System.Drawing; public class PremiereFenetre : Form { private Label message; private Button fermer; public PremiereFenetre() { SuspendLayout(); Text = "Une premire fentre"; // Le titre de la fentre Size = new Size(200, 150); // La taille initiale MinimumSize = new Size(200, 150); // La taille minimale

Programmation C sharp/Interfaces graphiques

97

// Le label "Hello world !" message = new Label(); message.Text = "Hello World !"; message.AutoSize = true; // Taille selon le contenu message.Location = new Point(50, 30);// Position x=50 y=30 // Le bouton "Fermer" fermer = new Button(); fermer.Text = "Fermer"; fermer.AutoSize = true; // Taille selon le contenu fermer.Location = new Point(50, 60);// Position x=50 y=60 fermer.Click += new System.EventHandler(fermer_Click); // Ajouter les composants la fentre Controls.Add(message); Controls.Add(fermer); ResumeLayout(false); PerformLayout(); } // Gestionnaire d'vnement private void fermer_Click(object sender, EventArgs evt) { // Fin de l'application : Application.Exit(); } static void Main() { // Pour le style XP : Application.EnableVisualStyles(); // Lancement de la boucle de messages // pour la fentre passe en argument : Application.Run(new PremiereFenetre()); } } Les proprits des composants sont initialises. Puis les composants sont ajouts la collection Controls des composants de la fentre. La gestion de l'vnement du clic sur le bouton se fait l'aide de l'event Click. Si la compilation se droule bien, le lancement de l'application affiche la fentre suivante :

Programmation C sharp/Interfaces graphiques

98

Cette fentre est redimensionnable, mais ne peut tre plus petite que la taille minimale spcifie dans le fichier source par la proprit MinimumSize.

L'interface avec un diteur graphiqueun diteur graphique permet de crer facilement l'interface graphique grce une barre d'outils permettant d'ajouter des composants la fentre de l'application, et de modifier leur proprits. Les ressources associes l'interface graphique sont : les icnes, dont celle de l'application affiche dans le coin suprieur gauche de la fentre, les images, les curseurs de souris personnaliss, les chanes de caractres (ressources en plusieurs langues).

Les diteurs disponibles sont : Visual Studio et sa version Express gratuite, le plus diffus SharpDevelop, un diteur dvelopp par une communaut de passionns MonoDevelop, un diteur dvelopp par le projet Mono

Les composantsTous les composants ont pour classe de base System.Windows.Forms.Control. Cette classe dfinit les fonctionnalits communes tous les composants.

Les vnementsLa gestion des vnements est assure par l'utilisation d'events dont la mthode delegate correspondante a la signature suivante : void nom_method(object sender, nom_vnementEventArgs e) Le premier argument indique la source de l'vnement (le contrle). Le deuxime argument donne des informations sur l'vnement (position de la souris, touche utilise, ...).

Programmation C sharp/Interfaces graphiques/Graphique vectoriel

99

Programmation C sharp/Interfaces graphiques/Graphique vectorielEspaces de nomSystem.Drawing.Drawing2D Cet espace de nom contient des classes permettant la conception de graphiques vectoriels avancs en 2D.

Un premier graphiqueusing using using using using using System; System.ComponentModel; System.Collections.Generic; System.Drawing; System.Drawing.Drawing2D; System.Windows.Forms;

namespace test { public partial class Form1 : Form { private int yPos = 40; private PictureBox pictureBox1; private Graphics g; public Form1() { this.InitializeComponent(); this.Show(); } private void InitializeComponent() { this.pictureBox1 = new PictureBox(); ((ISupportInitialize) this.pictureBox1).BeginInit(); this.SuspendLayout(); // // pictureBox1 // this.pictureBox1.Location = new Point(12, 12); this.pictureBox1.Name = "pictureBox1"; this.pictureBox1.Size = new Size(268, 112); this.pictureBox1.TabIndex = 0; this.pictureBox1.TabStop = false; // // Form1

Programmation C sharp/Interfaces graphiques/Graphique vectoriel // this.ClientSize = new Size(292, 141); this.Controls.Add(this.pictureBox1); this.Name = "Form1"; ((ISupportInitialize) this.pictureBox1).EndInit(); this.ResumeLayout(false); } static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } private void Show() { Bitmap bmp = new Bitmap( pictureBox1.Width, pictureBox1.Height); using (Graphics image = Graphics.FromImage(bmp)) { Pen myPen1 = new Pen(Color.Red); Pen myPen2 = new Pen(Color.Black); myPen1.Width = 5; myPen2.Width = 5; SolidBrush myBrush = new SolidBrush(Color.Red); Font myFont = new Font("Times New Roman", 24); // smile image.DrawLine(myPen2, 10, 5, 20, 5); image.DrawLine(myPen2, 55, 5, 65, 5); image.DrawBezier(myPen2, 15, 15, 15, 40, 60, 40, 60, 15); image.DrawString("~heLLo wErld ~", myFont, myBrush, 10, (this.yPos = this.yPos + 25)); } // using pictureBox1.Image = bmp; } } } Les mthodes appliques ici sont issues de la classe Graphics de .NET.

100

Programmation C sharp/Interfaces graphiques/Graphique vectoriel Pour afficher l'image il faut initialiser auparavant un constructeur de cette classe ou l'appeler par un vnement on_click par exemple.

101

Quelques mthodesLa classe Graphics comprend de nombreuses autres mthodes du genre. Dont : 1. DrawArc : Dessine un arc reprsentant une partie d'une ellipse indique par une paire de coordonnes, d'une largeur, et d'une taille. 2. DrawBezier : Dessine une cannelure de Bzier dfinie par quatre structures de point. 3. DrawBeziers : Tire une srie de cannelures de Bzier d'un choix de structures de point. 4. DrawClosedCurve : Dessine une cannelure cardinale ferme dfinie par un choix de structures de point. 5. DrawCurve : Dessine une cannelure cardinale par un choix indiqu de structures de point. 6. DrawEllipse : Dessine une ellipse dfinie par un rectangle de bondissement indiqu par une paire des coordonnes, d'une taille, et d'une largeur. 7. DrawIcon : Dessine l'image reprsente par l'icne indique aux coordonnes indiques. 8. DrawIconUnstretched : dessine l'image reprsente par l'icne indique sans mesurer l'image. 9. DrawImage : Dessine l'image indique l'endroit indiqu et avec le format document. 10. DrawImageUnscaled : Dessine l'image indique en utilisant son taille physique originale l'endroit indiqu par une paire du mme rang. 11. DrawImageUnscaledAndClipped : dessine l'image indique sans graduation et agrafes il, au besoin, l'ajustement dans le rectangle indiqu. 12. DrawLine : Trace une ligne reliant les deux points indiqus par les paires du mme rang. 13. DrawLines : Dessine une srie de ligne segments qui relient un choix de structures de point. dessine un GraphicsPath. 14. DrawPie : Dessine une forme de pt en crote dfinie par une ellipse indique par une paire du mme rang, une largeur, une taille, et deux lignes radiales. 15. DrawPolygon : Dessine un polygone dfini par un choix de structures de point. 16. DrawRectangle : Dessine un rectangle indiqu par une paire du mme rang, une largeur, et une taille. 17. DrawRectangles : Dessine une srie de rectangles indiqus par des structures de Rectangle. Cordon Surcharg. Dessine la corde indique des textes l'endroit indiqu avec la brosse indique et la police objecte.

Programmation C sharp/Fonctions asynchrones

102

Programmation C sharp/Fonctions asynchronesL'appel une fonction se fait de manire synchrone : aucune autre instruction n'est excute avant que la fonction ne retourne une valeur. Cependant certaines fonctions prennent beaucoup de temps, en particulier les oprations d'entres-sorties, et les fonctions de communication par rseau informatique. Pour ce genre de fonction, l'API .Net possde souvent deux versions de la mthode : Une mthode synchrone qui attend la fin de l'opration avant d'en retourner le rsultat, Une mthode asynchrone demandant au pool de threads standard d'effectuer l'opration, puis retourne immdiatement la mthode appelante.

Syntaxe et utilisation des mthodes asynchronesUne mthode synchrone est dclare selon la syntaxe suivante : type_retour nom_methode ( arguments... ) La version asynchrones utilise deux autres mthodes. La premire commence par Begin et demande au pool de threads standard d'effectuer l'opration. Une fois l'opration termine, un delegate est appel. Celui-ci appelle alors la mthode dont le nom commence par End pour rcuprer la valeur retourne par la mthode asynchrone. Ces deux mthodes ont la syntaxe suivante : IAsyncResult Beginnom_methode ( arguments_non_ref..., AsyncCallback callback, object state ) type_retour Endnom_methode ( IAsyncResult, arguments_ref ) Les arguments de la mthode synchrone se retrouvent rpartis entre les deux mthodes : Les paramtres passs par valeur sont passs la mthode Begin, Les paramtres de sorties (out et ref) sont passs la mthode End. La mthode Begin possde deux arguments supplmentaires : Un delegate de type AsyncCallback appel quand l'opration est termine (celui-ci doit alors appeler la mthode End correspondante), Un objet transmettre au delegate.

Le delegate AsyncCallbackLa syntaxe du delegate AsyncCallback est la suivante : public delegate void AsyncCallback(IAsyncResult result) Le paramtre result est une interface de type IAsyncResult correspondant celui retourn par la mthode Begin, et doit tre pass la mthode End.

L'interface IAsyncResultL'interface IAsyncResult possde les proprits en lecture seule suivantes : object AsyncState Cet objet correspond celui transmis la mthode Begin. WaitHandle AsyncWaitHandle

Programmation C sharp/Fonctions asynchrones Cet objet de synchronisation est mis dans l'tat signal quand l'opration est termine. bool IsCompleted Ce boolen vaut true (vrai) lorsque l'opration est termine. bool CompletedSynchronously Ce boolen vaut true (vrai) si l'opration s'est termine de manire synchrone.

103

Programmation C sharp/Threads et synchronisationUn thread est un contexte d'excution ayant sa propre pile de paramtres et de variables locales, mais partageant les mme variables globales (variables statiques des classes) que les autres threads du mme processus (la mme instance d'une application cre au moment de son lancement). Initialement, un processus ne possde qu'un seul thread. En gnral, celui-ci cre d'autres threads pour le traitement asynchrone de la file de messages provenant du systme d'exploitation (gestion des vnements), du matriel gr, ...

Crer et dmarrer un threadUn thread est cr pour effectuer une tche en parallle d'une autre. Si l'application possde une interface graphique et doit effectuer une tche qui prend du temps (calcul, tlchargement, ...), si un seul thread est utilis, durant la longue tche l'interface graphique est inutilisable. Il vaut mieux effectuer la tche longue dans un nouveau thread afin que l'utilisateur puisse continuer utiliser l'interface graphique (pour annuler cette tche par exemple). Les threads sont galement ncessaires pour grer plusieurs tches indpendantes les unes des autres, comme par exemple pour un serveur, la gestion de connexions simultanes avec plusieurs clients. Dans ce cas, chaque thread effectue les mmes tches. Ils sont en gnral grs par un ensemble de threads (Thread pool en anglais). Les threads et les outils associs sont grs par les classes de l'espace de nom System.Threading. La classe Thread gre un thread. Son constructeur accepte comme premier paramtre : soit un dlgu de type ThreadStart : delegate void ThreadStart() soit un dlgu de type ParameterizedThreadStart : delegate void ParameterizedThreadStart(object parameter) Le second paramtre est optionnel : int maxStackSize. Il indique la taille maximale de la pile allouer au nouveau thread. Une fois le thread cr, il faut appeler la mthode Start pour dmarrer le thread : soit Start() si le delegate n'a aucun paramtre (ThreadStart), soit Start(object parameter) si le delegate accepte un paramtre de type object (ParameterizedThreadStart). Exemple 1 : // La tche qui prend du temps ... private void longTask() { Console.WriteLine("Dbut de la longue tche dans le thread "

Programmation C sharp/Threads et synchronisation + Thread.CurrentThread.GetHashCode()); //... } // Dmarre un nouveau thread pour la mthode longTask() public void StartLongTask() { Console.WriteLine("Cration d'un thread partir du thread " + Thread.CurrentThread.GetHashCode()); Thread th = new Thread( new ThreadStart( this.longTask ) ); th.Start(); } Exemple 2 : Une mthode acceptant un paramtre. // La tche qui prend du temps ... private void telecharger(string url) { Console.WriteLine("Dbut du tlchargement de " + url + " dans le thread " + Thread.CurrentThread.GetHashCode()); //... } // Dmarre un nouveau thread pour la mthode telecharger() public void CommencerATelecharger(string url) { Console.WriteLine("Cration d'un thread partir du thread " + Thread.CurrentThread.GetHashCode()); Thread th = new Thread( new ParameterizedThreadStart( this.telecharger ) ); th.Start( url ); } Exemple 3 : Si la mthode doit accepter plusieurs paramtres, il faut passer un tableau de paramtres. Puisqu'un tableau est egalement un objet, le tableau peut tre pass sous la forme d'une rfrence d'objet, qui sera reconverti en tableau dans la mthode du delegate. // La tche qui prend du temps ... private void telecharger(object object_parameters) { object[] parameters = (object[]) object_parameters; string url = (string) parameters[0]; int tentatives = (int) parameters[1]; Console.WriteLine("Dbut du tlchargement de " + url +

104

Programmation C sharp/Threads et synchronisation " ("+tentatives+" tentatives) dans le thread " + Thread.CurrentThread.GetHashCode()); //... } // Dmarre un nouveau thread pour la mthode telecharger() public void CommencerATelecharger(string url, int tentatives) { Console.WriteLine("Cration d'un thread partir du thread " + Thread.CurrentThread.GetHashCode()); Thread th = new Thread( new ParameterizedThreadStart( this.telecharger ) ); th.Start( new object[] { url, tentatives } ); }

105

Attendre la fin d'un threadUne fois qu'un thread a dmarr, la mthode join peut tre appele pour attendre que la mthode du thread se termine. Cette mthode est surcharge : void Join() : attend indfiniment que le thread se termine, bool Join(int millisecondsTimeout) : attend que le thread se termine dans le temps imparti spcifi en millisecondes. Cette mthode retourne true si le thread s'est termin dans le temps imparti, et false sinon, bool Join(TimeSpan timeout) : cette mthode fonctionne de la mme manire que la prcdente, except que le temps imparti est spcifi par une structure de type System.TimeSpan. Exemple : // Dmarre un nouveau thread pour la mthode longTask() public void startLongTask() { Console.Writeline("Cration d'un thread partir du thread " + Thread.CurrentThread.GetHashCode()); Thread th = new Thread( new ThreadStart( this.longTask ) ); Console.Writeline("Dmarrage du thread " + th.GetHashCode() ); th.Start(); Console.Writeline("Attente de la fin du thread " + th.GetHashCode() + " pendant 5 secondes ..."); bool fini = th.Join(5000); // 5000 ms if (!fini) // si pas fini {

Programmation C sharp/Threads et synchronisation Console.Writeline("Le thread " + th.GetHashCode() + " n'a pas termin au bout de 5 secondes, attente indfinie ..."); th.Join(); } Console.Writeline("Le thread " + th.GetHashCode() + " a termin sa tche."); }

106

Suspendre et Arrter un threadSuspendre un threadPour suspendre un thread, il faut appeler la mthode Suspend(). Le thread est alors suspendu jusqu' l'appel la mthode Resume(). Cependant ces deux mthodes sont obsoltes, car un thread suspendu dtient toujours les ressources qu'il avait acquis avant sa suspension. Ce problme risque de provoquer le blocage d'autres threads tant que celui-l est suspendu.

Arrter un threadL'arrt d'un thread peut tre demand en appelant la mthode Interrupt(). Cette mthode provoque le lancement d'une exception lorsque le thread appelera une mthode d'entre-sortie. Donc l'arrt du thread n'est pas instantan. Cependant l'appel cette mthode peut interrompre le thread n'importe quel moment de son excution. Il faut donc prvoir que ce genre d'exception soit lanc pour pouvoir librer les ressources dans un bloc try..finally, voire utiliser using). Une solution alternative est de tester une condition de terminaison du thread. Ceci permet de spcifier o le thread peut se terminer, et librer les ressources correctement. Exemple : public void UnThread() { // ... initialisation while ( continuer_thread ) { // ... tches du thread } // ... libration des ressources } Cependant, l'utilisation d'un bloc try..finally (ou du mot cl using) est tout de mme ncessaire au cas o le systme interromperait le thread (fin brutale de l'application par exemple).

Programmation C sharp/Threads et synchronisation

107

Proprits d'un threadVoici une liste des principales proprits de la classe Thread : bool IsAlive (lecture seule) Indique si le thread est toujours actif. bool IsBackground Indique si le thread est un thread d'arrire plan. Un thread d'arrire plan ne permet pas de maintenir l'excution d'une application. C'est dire qu'une application est termine ds qu'il n'y a plus aucun thread de premier plan en cours d'excution. bool IsThreadPoolThread (lecture seule) Indique si le thread appartient au pool de threads standard. int ManagedThreadId (lecture seule) Retourne l'identifiant attribu au thread par le framework .Net. string Name Nom attribu au thread. ThreadPriority Priority Priorit du thread : Lowest : priorit la plus basse, BelowNormal : priorit infrieure normale, Normal : priorit normale, AboveNormal : priorit suprieure normale, Highest : priorit la plus haute.

ThreadState ThreadState (lecture seule) Etat actuel du thread. Cette proprit est une combinaison de valeurs de l'numration ThreadState : Running = 0x00000000 : en cours d'excution, StopRequested = 0x00000001 : arrt demand, SuspendRequested = 0x00000002 : suspension demande, Background = 0x00000004 : thread d'arrire plan, Unstarted = 0x00000008 : thread non dmarr, Stopped = 0x00000010 : thread arrt, WaitSleepJoin = 0x00000020 : thread en attente (wait, sleep, ou join), Suspended = 0x00000040 : thread suspendu, AbortRequested = 0x00000080 : abandon demand, Aborted = 0x00000100 : thread abandonn.

Programmation C sharp/Threads et synchronisation

108

Le pool de threadsUn pool de threads est associ chaque processus. Il est compos de plusieurs threads rutilisables effectuant les tches qu'on lui assigne dans une file d'attente. Une tche est place dans la file d'attente, puis on lui affecte un thread inocup qui l'effectuera, puis le thread se remet en attente d'une autre tche. Une partie de ces threads est consacre aux oprations d'entres-sorties asynchrones. Le pool de threads est gr par les mthodes statiques de la classe ThreadPool. Par dfaut, le pool contient 25 threads par processeur. La mthode QueueUserWorkItem permet d'ajouter une nouvelle tche : bool QueueUserWorkItem ( WaitCallback callback, object state ) Le premier paramtre est un dlgu dont la signature est la suivante : delegate void WaitCallback(object state) Le second paramtre est optionnel et contient l'argument pass au dlgu. Le dlgu pass en paramtre effectuera la tche, dans le thread qui lui sera attribu.

Synchronisation entre les threadsLe fait que tous les threads d'un mme processus partagent les mmes donnes signifie que les threads peuvent accder simultanment un mme objet. Si un thread modifie un objet (criture, en utilisant une mthode de l'objet par exemple) pendant qu'un autre thread rcupre des informations sur cet objet (lecture), ce dernier peut obtenir des donnes incohrentes rsultant d'un tat intermdiaire temporaire de l'objet accd. Pour rsoudre ce genre de problme, des outils de synchronisation permettent de suspendre les threads essayant d'accder un objet en cours de modification par un autre thread.

MoniteurUn moniteur (monitor en anglais) ne permet l'accs qu' un seul thread la fois. C'est dire que si plusieurs threads essaye d'accder au mme moniteur, un seul obtiendra l'accs, les autres tant suspendus jusqu' ce qu'ils puissent leur tour dtenir l'accs exclusif. La classe Monitor gre ce type d'objet de synchronisation. Toutes les mthodes de cette classe sont statiques. Les principales mthodes sont : void Enter(object obj) Cette mthode suspend le thread appelant si un autre thread possde dj l'accs exclusif, ou retourne immdiatement sinon. void Exit(object obj) Cette mthode met fin l'accs exclusif par le thread appelant, et permet un thread suspendu d'obtenir l'accs exclusif son tour. bool TryEnter(object obj) Cette mthode permet de tenter d'obtenir l'accs exclusif. Elle retourne true si l'accs exclusif est obtenu, false sinon. bool TryEnter(object obj,int milliseconds) Cette mthode permet de tenter d'obtenir l'accs exclusif, dans le temps imparti spcifi en millisecondes. Elle retourne true si l'accs exclusif est obtenu, false sinon.

Programmation C sharp/Threads et synchronisation L'objet pass en paramtre identifie le moniteur accd. C'est dire que tout objet peut tre utilis comme moniteur. En C#, tout est objet, mme les chanes de caractres, et les valeurs numriques et boolennes. Cependant, il n'est pas recommand d'utiliser de telles valeurs ou des rfrences publiques, car ce sont des rfrences globales. Il est prfrable d'utiliser des membres privs, voire des variables locales. Exemple : using System; using System.Threading; public class TestMonitor { private object synchro = new object(); public void MethodeThread() { int id = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Dbut du thread " + id ); Monitor.Enter( synchro ); Console.WriteLine("Le thread " + id + " entre exclusivement ..." ); Thread.Sleep(1000); // attend 1 seconde Console.WriteLine("Le thread " + id + " sort ..." ); Monitor.Exit( synchro ); Console.WriteLine("Fin du thread " + id ); } public void Test() { // 2 threads Thread thread1 = new Thread( new ThreadStart( MethodeThread ) ), thread2 = new Thread( new ThreadStart( MethodeThread ) ); thread1.Start(); thread2.Start(); } public static void Main() { new TestMonitor().Test(); } } Ce programme affiche : Dbut du thread 3 Le thread 3 entre exclusivement ... Dbut du thread 4

109

Programmation C sharp/Threads et synchronisation Le thread 3 sort ... Le thread 4 entre exclusivement ... Fin du thread 3 Le thread 4 sort ... Fin du thread 4 Ce programme ne tient pas compte des exceptions. Il faut cependant les prvoir pour s'assurer de librer le moniteur, en utilisant un bloc try..finally : ... public void MethodeThread() { int id = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Dbut du thread " + id ); Monitor.Enter( synchro ); try { Console.WriteLine("Le thread " + id + " entre exclusivement ..." ); Thread.Sleep(1000); // attend 1 seconde Console.WriteLine("Le thread " + id + " sort ..." ); } finally { Monitor.Exit( synchro ); } Console.WriteLine("Fin du thread " + id ); } ...

110

Le mot cl lockLe mot cl lock est utilisable pour produire un code quivalent au prcdent : ... public void MethodeThread() { int id = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Dbut du thread " + id ); lock( synchro ) // tat signal Cette classe possde le constructeur suivant : public EventWaitHandle(bool initialState, EventResetMode mode); Les paramtres sont les suivants : initialState tat initial : signal (true) ou non-signal (false). mode Mode pour le retour l'tat non-signal : AutoReset ou ManualReset : ManualReset : le retour l'tat non-signal (reset) se fait explicitement en appelant la mthode Reset(). AutoReset : le retour l'tat non-signal est automatiquement effectu quand un thread est activ, c'est dire quand il a termin d'attendre l'tat signal avec une mthode wait (WaitOne, WaitAny ou WaitAll). Il y a une sous-classe pour chacun des deux modes (voir ci-dessous pour une description).

Programmation C sharp/Threads et synchronisation Synchronisation inter-processus Cette classe possde galement le constructeur suivant : public EventWaitHandle(bool initialState, EventResetMode mode, string name, ref Boolean createdNew, System.Security.AccessControl.EventWaitHandleSecurity eventSecurity); Les trois paramtres supplmentaires sont tous optionnels et sont utiliss pour le partage au niveau systme et donc pour la synchronisation entre processus : name Nom unique identifiant cette instance de la classe EventWaitHandle. createdNew Rfrence une variable boolenne que la fonction va utiliser pour indiquer si un nouvel objet EventWaitHandle a t cr (true) ou s'il existe dj (false). eventSecurity Dfinit les conditions d'accs l'objet partag. Elle possde galement une mthode statique permettant de retrouver une instance de la classe EventWaitHandle existante partage au niveau systme : public static EventWaitHandle OpenExisting(string name, System.Security.AccessControl.EventRights rights); Le paramtre rights est optionnel et permet d'accder l'objet partag. Sous-classes Cette classe a deux sous-classes : AutoResetEvent : Le retour l'tat non-signal est automatique. Une fois que l'tat signal est obtenu par un thread (fin de l'attente par une mthode wait), l'objet AutoResetEvent revient l'tat non-signal, empchant un autre thread d'obtenir l'tat signal. ManualResetEvent : Le retour l'tat non-signal se fait explicitement. Ces deux sous-classes ont un constructeur qui accepte comme paramtre un boolen initialState indiquant son tat initial : true pour l'tat signal, false pour l'tat non-signal. Exemple : using System; using System.Threading; class Exemple { static AutoResetEvent evenementTermine; static void AutreThread() { Console.WriteLine(" Autre thread : attente...");

113

0% accompli,

evenementTermine.WaitOne(); // Attend tat signal + Reset

Programmation C sharp/Threads et synchronisation (auto) // l'tat a t signal, mais retour l'tat non-signal // maintenant que l'appel WaitOne est termin. Console.WriteLine(" attente..."); Autre thread : 50% accompli,

114

evenementTermine.WaitOne(); // Attend tat signal + Reset (auto) // l'tat a t signal, mais retour l'tat non-signal // maintenant que l'appel WaitOne est termin. Console.WriteLine(" } static void Main() { evenementTermine = new AutoResetEvent(false); Console.WriteLine("Main: dmarrage de l'autre thread..."); Thread t = new Thread(AutreThread); t.Start(); Console.WriteLine("Main: tche 1/2 : 1 seconde ..."); Thread.Sleep(1000); evenementTermine.Set(); // -> tat signal Console.WriteLine("Main: tche 2/2 : 2 secondes ..."); Thread.Sleep(2000); evenementTermine.Set(); // -> tat signal Console.WriteLine("Main: fin des tches."); } } Autre thread : 100% accompli, termin.");

Verrou d'exclusion mutuelleUn verrou d'exclusion mutuelle (mutex en abrg) permet de donner un accs exclusif pour une ressource un seul thread la fois. Cette classe drive de la classe WaitHandle dcrite avant. Pour obtenir l'accs, il faut appeler une mthode wait (WaitOne par exemple), c'est dire attendre l'tat signal. La mthode suivante permet de librer le verrou en positionnant l'tat signal : public void ReleaseMutex(); // -> tat signal Comme pour une instance de la classe AutoResetEvent, le retour l'tat non-signal est automatique, quand un thread sort de la fonction d'attente. Cette classe possde le constructeur suivant :

Programmation C sharp/Threads et synchronisation public Mutex(bool initiallyOwned, string name, ref Boolean createdNew, System.Security.AccessControl.MutexSecurity mutexSecurity); Tous les paramtres sont optionnels : initiallyOwned : true si le mutex est dans l'tat non-signal et appartient au thread appelant, false sinon (tat signal). Les autres paramtres servent la synchronisation inter-processus et sont dcrit dans la section "Synchronisation inter-processus" prcdente. Cet objet est ddi la synchronisation inter-processus. Pour de l'exclusion mutuelle entre threads du mme processus, du point de vue des performances, il est prfrable d'utiliser un moniteur, ou l'instruction lock.

115

Programmation C sharp/ProcessusPour chaque application lance, le systme d'exploitation cre un nouveau processus grant l'tat de l'application : mmoire (variables, donnes), code en cours d'excution (threads), variables d'environnement, ressources alloues (fichiers ouverts, sockets connectes, ...). Chaque processus possde trois flux de communication : le flux d'entre (gnralement associ l'entre standard stdin ) permet au processus de recevoir des donnes de l'utilisateur, ou du processus appelant, le flux de sortie (gnralement associ la sortie standard stdout ) permet au processus d'afficher sous forme textuelle ses rsultats l'utilisateur, ou de les transmettre au processus appelant, le flux d'erreur (gnralement associ l'erreur standard stderr ) permet au processus de notifier les messages erreurs l'utilisateur, ou au processus appelant.

Programmation C sharp/Entres-sorties

116

Programmation C sharp/Entres-sortiesLes fonctions d'entres-sorties utilisent l'espace de nom System.IO.

La classe StreamLa classe abstraite Stream possde des mthodes permettant la fois de lire et d'crire. Cependant, l'criture ou la lecture peut ne pas tre autorise (fichier en lecture seule, ...).

PropritsLa classe Stream possde les proprits suivantes : bool CanRead (lecture seule) Cette proprit vaut true quand la lecture est possible. bool CanWrite (lecture seule) Cette proprit vaut true quand l'criture est possible. bool CanSeek (lecture seule) Cette proprit vaut true quand le positionnement dans le flux est possible (mthode Seek ou proprit Position). bool CanTimeout (lecture seule) Cette proprit vaut true quand le flux peut expirer (fin de connexion pour une socket, ...). long Length (lecture seule) Longueur du flux en nombre d'octets. long Position Position courante dans le flux en nombre d'octets depuis le dbut. int ReadTimeout Temps imparti pour la mthode Read, en millisecondes. L'accs cette proprit peut dclencher le lancement d'une exception de type InvalidOperationException si la fonctionnalit n'est pas supporte. int WriteTimeout Temps imparti pour la mthode Write, en millisecondes. L'accs cette proprit peut dclencher le lancement d'une exception de type InvalidOperationException si la fonctionnalit n'est pas supporte.

MthodesLes mthodes de la classe Stream sont les suivantes : void Close() Ferme le flux. void Dispose() Libre les ressources occupes par le flux. void Flush() Cette mthode vide les buffers d'criture vers le support associ (fichier, socket, ...). int ReadByte() Cette mthode lit un octet et retourne sa valeur, ou -1 en cas d'erreur.

Programmation C sharp/Entres-sorties void WriteByte(byte value) Cette mthode crit un octet. int Read(byte[] buffer, int offset, int count) Cette mthode lit count octets dans le buffer spcifi, partir de l'offset offset dans le tableau buffer. Elle retourne le nombre d'octets effectivement lus. void Write(byte[] buffer, int offset, int count) Cette mthode crit count octets du tableau buffer dont le premier octet est situ l'offset offset. void Seek(long offset, SeekOrigin origin) Dplace le pointeur d'criture/lecture de offset octets depuis l'origine indique: SeekOrigin.Begin : depuis le dbut du flux, SeekOrigin.End : partir de la fin du flux, SeekOrigin.Current : partir de la position courante dans le flux. void SetLength(long value) Cette mthode modifie la longueur totale du flux (troncature ou remplissage avec des octets nuls).

117

Mthodes asynchronesLes mthodes Read et Write utilisant un tableau d'octet existent galement en version asynchrone : IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback, object). int EndRead(IAsyncResult result). IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback, object). void EndWrite(IAsyncResult result).

Membres statiquesLa classe Stream possde galement deux membres statiques : La constante Null est un flux dont la lecture ou l'criture ne produit aucun effet. La mthode statique Synchronized retourne une version synchronise du flux pass en paramtre.

Fonctions asynchronesLes fonctions dont le retour peut prendre du temps existent galement en version asynchrone. La mthode appele est alors celle dont le nom commence par Begin. Elle demande au pool de threads standard d'excuter l'opration. Une fois l'opration termine, le delegate pass la fonction Begin doit appeler la fonction End correspondante pour rcuprer le rsultat.

ExempleCet exemple utilise la version asynchrone de la mthode Read de la classe Stream. class LectureAsync { private byte[] buffer = new byte[4000]; public void commencerLecture(Stream s) {

Programmation C sharp/Entres-sorties // Commencer la lecture IAsyncResult iar = s.BeginRead(buffer, 0, buffer.length, finLecture, s); // et retour immmdiat // La mthode finLecture transmise en 4me paramtre sera appele // quand la lecture du tableau d'octets sera termine. } public void finLecture(IAsyncResult result) //AsyncCallback { // Stream : le dernier argument transmis BeginRead Stream s=(Stream)result.AsyncState; // rcuprer le nombre d'octets lus int nb_octets = s.EndRead(result); } }

118

Flux de fichierLa classe FileStream drive de la classe Stream. Elle possde donc les mmes mthodes. La classe FileStream possde les constructeurs suivants : public FileStream(string path, System.IO.FileMode mode, [ System.IO.FileAccess access, [ System.IO.FileShare share, [ int bufferSize, [ System.IO.FileOptions options ] ] ] ] ); public FileStream(string path, System.IO.FileMode mode, [ System.IO.FileAccess access, [ System.IO.FileShare share, [ int bufferSize, [ bool useAsync ] ] ] ] ); public FileStream(string path, System.IO.FileMode mode, System.Security.AccessControl.FileSystemRights rights, System.IO.FileShare share, int bufferSize, System.IO.FileOptions options, [ System.Security.AccessControl.FileSecurity fileSecurity ] ); Les crochets indiquent les paramtres optionnels.

Programmation C sharp/La srialisation

119

Programmation C sharp/La srialisationLa srialisation est un procd d'entre-sortie permettant de sauvegarder et recharger l'tat d'un objet. Cette fonctionnalit permet de faire abstraction du format de fichier utilis. Celui-ci dpend de l'outil de srialisation utilis. L'tat d'un objet correspond l'ensemble des valeurs de ses champs. Les prorits sont calcules en fonction des champs, et le code des mthodes ne change pas au cours de l'excution.

AttributsL'attribut System.SerializableAttribute marque les classes dont les instances peuvent tre srialises. Si l'attribut est absent pour une classe, la srialisation de ses instances provoquera une exception. Exemple : [Serializable] class Facture { public string Client; public double TotalHT; public double TotalTTC; } L'attribut System.NonSerializedAttribute marque les champs qu'il ne faut pas enregistrer. C'est le cas des champs dont on peut retrouver la valeur par calcul, par exemple. Exemple : [Serializable] class Facture { public string Client; public double TotalHT; [NonSerialized] public double TotalTTC; // = TotalHT * (1 + taux_TVA/100) } Quand la classe volue, de nouveaux champs sont ajouts la classe, d'autres sont retirs. L'attribut System.Runtime.Serialization.OptionalFieldAttribute marque les champs optionnels lors de la dsrialisation (lecture de l'objet). Il est donc possible de marquer les nouveaux champs comme optionnels, et garder les anciens champs (marqus optionnels galement) pour garder la compatibilit avec les anciens fichiers. Exemple : [Serializable] class Facture { public string Client; public double TotalHT; [NonSerialized]

Programmation C sharp/La srialisation public double TotalTTC; [OptionalField] public string AdresseLivraison; // Nouveau champ } Dans cet exemple, la classe Facture permettra de lire des fichiers d'objets Facture contenant le champ AdresseLivraison ou non.

120

La srialisationLe format de srialisation dpend de la classe utilise pour srialiser les objets.

La classe System.Runtime.Serialization.FormatterCette classe abstraite dfinit les mthodes suivantes : void Serialize( System.IO.Stream serializationStream, object graph); Cette mthode enregistre l'objet graph dans le flux d'entre-sortie spcifi. object Deserialize( System.IO.Stream serializationStream); Cette mthode retourne l'objet lu depuis le flux d'entre-sortie spcifi. Les classes drives dfinissent un format concret de srialisation : La classe System.Runtime.Serialization.Formatters.Binary.BinaryFormatter permet de srialiser dans un format binaire, La classe System.Runtime.Serialization.Formatters.Soap.SoapFormatter permet de srialiser au format SOAP. Une classe drive de System.Runtime.Serialization.Formatter srialise les attributs et les vnements d'un objet, quel que soit l'accs associ (public, protg, priv, ou par dfaut).

Format XMLLa classe System.Xml.Serialization.XmlSerializer permet de srialiser au format XML. Elle ne drive pas de la classe System.Runtime.Serialization.Formatter, et possde les mthodes suivantes : void Serialize( System.IO.Stream stream, object o); void Serialize( System.IO.TextWriter textWriter, object o); void Serialize( System.Xml.XmlWriter xmlWriter, object o); Ces mthodes enregistrent l'objet graph dans le flux d'entre-sortie spcifi. object Deserialize( System.IO.Stream stream);

Programmation C sharp/La srialisation object Deserialize( System.IO.TextReader textReader); object Deserialize( System.Xml.XmlReader xmlReader); Ces mthodes retournent l'objet lu depuis le flux d'entre-sortie spcifi. Pour le format XML, les attributs Serializable et NonSerialized sont ignors : Toute classe est srialisable en XML, L'attribut System.Xml.Serialization.XmlIgnoreAttribute marque les champs ignorer lors de la srialisation. La classe System.Xml.Serialization.XmlSerializer srialise les attributs et les proprits en lecture/criture publics d'un objet, si la valeur n'est pas nulle. Donc la srialisation en XML ignore : les attributs et proprits retournant une valeur nulle, les attributs et proprits protgs ou