Vous êtes sur la page 1sur 62

LE LANGAGE C#

Introduction au framework .NET

RECOMMENDATIONS
La matrise d'un langage passe par une pratique importante. Vous devez: - Lire et relire le cours en vous appuyant sur la bibio donne ci aprs - reprendre les exemples du poly dans Visual Studio (copier/coller) , les xcuter et les tudier. - Vous devez FAIRE les exercices d'auto apprentissage

BIBLIOGRAPHIE ET RESSOURCES Livres


Oreilly.CSharp.4.0.in.a.Nutshell.4th.Edition (le meilleur mon avis) en anglais Une rfrence: trs complet Ncessite mon avis quelques notions CSharp.2010.and.the.dotNET.4.Platform.5th.Edition: en anglais Bien C# et .Net - Versions 1 4 En francais Bon livre pour les dbutants Moins complet que CSharp.4.0.in.a.Nutshell APPRENTISSAGE DU LANGAGE C# 2008et du Framework .NET 3. Poly de cours de C# par Serge Tah En francais Pratique de .NET et C# (patrick SMACCHIA) En francais Mal structur mon avis: partie 1 du livre trs technique (informations que vous ne trouverez pas dans les autres livres) et partie 2: Trs bien

Internet
http://msdn.microsoft.com/fr-fr/library/ms229335(v=VS.80).aspx http://www.developpez.com/ www.codeproject.com/ http://www.codeguru.com/ Sur les design pattern des articles trs ditactiques: http://www.siteduzero.com/tutoriel-3-10601-programmation-en-java.html#part_65564 et tous les autres.

INTRODUCTION
Lobjectif de ce polycopi nest pas une prsentation exhaustive du langage C#. Pour cela une littrature nombreuse existe sur Internet (en version papier aussi dailleurs). Le C# peut tre considr comme une synthse du C++ et de Java. Tout en gardant les points forts du C++, il corrige certains points faibles et permet une abstraction de donnes plus pousse et une approche compltement oriente objet. Toutefois certains inconvnients existent savoir : Un langage qui reste en partie propritaire Langage Non temps rel ( ramasse miette non dterministe, langage intermdiaire interprt)

La plate forme .NET Framework

La premire couche CLS est compose des spcifications communes tous les langages qui veulent produire des applications .NET qui soient excutables dans cet environnement et les langages eux-mme. La seconde couche est un ensemble de composants graphiques disponibles dans Visual Studio .NET La troisime couche est constitue d'une vaste librairie de plusieurs centaines de classes La quatrime couche forme l'environnement d'excution commun (CLR ou CommonLanguage Runtime) de tous les programmes s'excutant dans l'environnement .NET. Le CLR excute un bytecode crit dans un langage intermdiaire (MSIL ou MicroSoft Intermediate Language

L'environnement d'excution du CLR


Le CLR (Common Language Runtime) est un environnement complet d'excution semblable au JRE de Sun pour Java : il est indpendant de l'architecture machine sous-jacente. Bien que se terminant par le suffixe exe, un programme issu d'une compilation sous .NET n'est pas un excutable en code natif. mais un bytecode en MSIL.Cela signifie que vous ne pourrez pas lexcuter directement sur un ordinateur qui n'aurait pas la machine virtuelle.NET.
Lorsque le processeur P n'est pas une machine qui existe physiquement mais un logiciel simulant (ou interprtant) une machine on appelle cette machine pseudomachine ou p-machine. Le programme source est alors traduit par le compilateur en instructions de la pseudo-machine et se dnomme pseudo-code. La p-machine standard peut ainsi tre implante dans n'importe quel ordinateur physique travers un logiciel qui simule son comportement; un tel logiciel est appel interprteur de la p-machine.

-3-

La compilation JIT progressive


JIT (Just-in-time) est une technique de traduction dynamique durant l'interprtation. La machine virtuelle CLR contient un compilateur optimiseur qui recompile localement le bytecode MSIL afin de n'avoir plus qu' faire excuter des instructions machines de base. Le compilateur JIT du CLR compile une mthode en code natif ds qu'elle est appele dans le code MSIL. Le processus recommence chaque fois qu'un appel de mthode a lieu sur une mthode non dj compile en code natif.

La compilation AOT
AOT (ahead-of-time) est une technique de compilation locale de tout le bytecode MSIL avant excution (semblable la compilation native). Le compilateur AOT du CLR compile, avant une quelconque excution et en une seule fois, toutes les lignes de code MSIL et gnre des images dexcutables destination du CLR.

-4-

ELEMENTS DE BASES DU C#
Les donnes natives

ATTENTION : le char est un nombre entier non sign sur 2 octets

Nature des objets


Le systme de types C# comporte les catgories suivantes : Types valeur Types rfrence (Types de pointeur) Les variables de types valeur stockent des donnes alors que les variables de types rfrence stockent les rfrences aux donnes. Les types rfrence sont galement considrs comme des objets. Les types pointeur ne peuvent tre utiliss qu'en mode non scuris et sont donc viter. Contrairement au C++ le programmateur ne matrise pas l'emplacement des objets en mmoire et que partiellement leur dure de vie ( c'est le ramasse miette qui est le matre d'uvre du cycle de vie des objets). Lemplacement des objets en mmoire dpendra de plusieurs paramres: - de leur nature :type valeur ou type rfrence - de la dure vie de l'objet o pour des dures courtes (registre processeur ou pile) o pour des dures longues: le TAS
Les variables

Les variables bases sur des types valeur contiennent directement des valeurs. L'attribution d'une variable de type valeur une autre, copie la valeur contenue,d'o le terme "type valeur" (copie par valeur) Cela est diffrent de l'assignation des variables de type rfrence, qui copient une rfrence vers l'objet mais pas l'objet lui-mme (copie des rfrences). //types flottant
y est de type variable. Le contenu de la variable reflte le contenu de la variable y x est de type rfrence. Le contenu de la variable contient "un lien" vers la donne situ ailleurs en mmoire. float y = 4.5f; short z = 5; double w = 1.7E+3; // declaration structure struct StructAmoi { int b; void meth(int a){ b = 1000+a; } } // instantiation structure StructAmoi y = new StructAmoi ( ) ;

Le tas est en fait un espace de mmoire vive disponible pour le processus courant, c'est--dire l'ensemble de votre programme (et de ses thread, s'il y en a plusieurs). La pile est une zone mmoire prive alloue pour chaque thread.

-5-

Les types "valeur" sont rpartis en deux catgories principales : Struct numrations Les struct sont rpartis dans les catgories suivantes : Types numriques Types intgraux (des entiers) Types virgule flottante decimal bool Structures dfinies par l'utilisateur.

Les rfrences
Prcision sur la notion de rfrence: - Une rfrence tablit "un lien" vers lobjet vis o Attention: une rfrence n'est pas l'adresse de l'objet rfrenc. Il peut s'agir par exemple d'un index ou identificateur spficique maintenu par le ramasse miette et /ou le CLR. - Une rfrence ne donne pas accs ladresse physique de lobjet - Les oprations arithmtiques sont interdites - Une rfrence doit tre initialise la cration - Une rfrence est nullable ( string chaine=NULL ;) - Une rfrence permet d'accder au contenu de l'objet vis et de le modifier - Une rfrence est de type variable: A l'instantt la rfrence est connect l'objet A puis t+1 l'objet B. Les mots cls suivants induisent la cration dune variable de type rfrence class string a = "hello"; interface string b = "h"; delegate // Append to contents of 'b' b += "ello"; object Console.WriteLine(a == b); string Console.WriteLine((object)a == (object)b); sans oublier les objets tableaux et chanes. Exemple:
classTypeRefExemple { publicfloatnote; publicstringnomEtudiant; }

TypeRefExempleRef1;//allocationd'unerfrence(noninitialise!) TypeRefExempleRef1=newTypeRefExemple();//crationd'unobjetdutypeTypeRefExemple,Ref1"pointe"versl'objet TypeRefExempleRef2=Ref1;//crationd'unenouvellerfrence"pointant"versl'objetprcdent

Req:

Ref1, et Ref2 se retrouve dans la pile du thread courant L'objet rfrenc est plac dans la TAS Nous avon sdonc 2 rfrnces mais un seul objet de type TypeRefExemple

Structure dun programme type console


using System; namespace date_test_minute { class Program { static void Main(string[] args) { // vos lignes de codes ici } } } -6Commentaires : using : permet de rajouter des composants logiciels namespace : permet de construire ses propres distributions de classes class : Une classe permet de regrouper au sein d'une mme structure le format des donnes qui dfinissent l'objet et les fonctions destines manipuler ces objets. On dit qu'une classe permet d'encapsuler les diffrents lments et les fonctions dans un ensemble appel objet

Un exemple tudier attentivement sur la cration d'objets (lisez les commentaires!):


usingSystem; namespaceExemple_valeur_reference { structTypeValExemple { publicintcode_Apoge; publicstringnomEtudiant; } classTypeRefExemple { publicfloatnote; publicstringnomEtudiant; } classProgram { staticvoidMain() { stringnom_1="Dupont";//typerfrence floatnote=13.5f;//typevaleur intcode=12321;//typevaleur stringnom_2;//typerfrence //creationdedeuxvariablesdutypeTypeValExemple TypeValExempleEtudiant1_TypeVal;//forme1 TypeValExempleEtudiant2_TypeVal=newTypeValExemple();//forme2d'allocation TypeRefExempleEtudiant3_TypeRef1;//rfrencenoninitialise TypeRefExemple Etudiant3_TypeRef2=new TypeRefExemple(); // fait rfrence au nouvel objet cre parl'oprarateurnew //lalignesuivantenecompilepas:Etudiant1_TypeValestunobjetnoninitialis!!! //Console.WriteLine("Etud1:"+Etudiant1_TypeVal.code_Apoge+"::"+Etudiant1_TypeVal.nomEtudiant); Etudiant2_TypeVal.code_Apoge=code; Etudiant2_TypeVal.nomEtudiant=nom_1; Etudiant1_TypeVal=Etudiant2_TypeVal;//2objetsspars:copieenvaleurchampparchamp Console.WriteLine("Etud1:"+Etudiant1_TypeVal.code_Apoge+"//"+Etudiant1_TypeVal.nomEtudiant); Console.WriteLine("Etud2 :" + Etudiant2_TypeVal.code_Apoge + "//" + Etudiant2_TypeVal.nomEtudiant); nom_2=nom_1; // ne pas confondre la variable note avec le champs note de l'objet Etudiant4_TypeRef de type TypeRefExemple Etudiant3_TypeRef2.note=note; Etudiant3_TypeRef2.nomEtudiant=nom_2; // la ligne suivante ne compile pas:TypeRefExemple n'est pas un objet( ie une variable) mais un typededonnes //TypeRefExemple.nomEtudiant="test"; // la ligne suivante ne compile pas:Etudiant3_TypeRef ne fait rfrence pour l'instant aucun objet //Etudiant3_TypeRef1.nomEtudiant="test"; Etudiant3_TypeRef1=Etudiant3_TypeRef2;//1seulobjetenmmoiremais2rfrences Console.WriteLine("Etud:{0}//{1}",Etudiant3_TypeRef1.note,Etudiant3_TypeRef1.nomEtudiant); //lanotedel'tudiant3estmodifie Etudiant3_TypeRef1.note=20; //cechangementaparaitaussisurl'etudiant4 Console.WriteLine("Etud:{0}//{1}",Etudiant3_TypeRef2.note,Etudiant3_TypeRef2.nomEtudiant); //NORMAL:1seulobjetmais2rfrencecemmeobjet! Console.ReadKey();//attentetouche } } }

-7-

Flux dentre/sortie standard


La classe System.Console donne accs aux oprations d'criture cran (Write, WriteLine) et de lecture clavier (Read,ReadLine). La classe Console a 3 proprits In,Out et Error qui sont des flux d'criture de type TextWriter . Console.WriteLine() est quivalent Console.Out.WriteLine() et crit sur le flux Out associ habituellement l'cran. Console.Error.WriteLine() crit sur le flux Error, habituellement associ lui aussi l'cran. Attention :La mthode ReadLine renvoie
Les formateurs

Ils sont bass sur une chane de caractre Console.Write (String, Object, Object) o String est une chane type formateur Formateur de nombres

string myName = "Fred"; Console.WriteLine ("Name = {0}, hours = {1:hh}", myName, DateTime.Now); // {} indique le numro de largument afficher // Name = Fred, hours = 05 Console.WriteLine("(X) Hexa:{0:X}\n (D) Decimal: {0:D}\n", 255); // (X) Hexa:80 //(D) Decimal: 128 Double myDouble = 1234567890; Console.WriteLine(" {0:(###) ### - ####}", myDouble); // The value of myString is "(123) 456 7890".

Formateur de dates
int i; char c; while (true) { i = Console.Read (); if (i == -1) break; c = (char) i; Console.WriteLine ("Echo: {0}", c); } Console.WriteLine ("Done"); return 0;

Formateur spcifiques

Exemples complmentaires: Saisie clavier avec conversion string-> float

static void Main(string[] args) { float a, b, c; // coeff equation Console.Write("Entrer a="); a = float.Parse(Console.ReadLine()); Console.Write("Entrer b="); b = float.Parse(Console.ReadLine()); Console.WriteLine("Entrer c="); c = float.Parse(Console.ReadLine()); }

-8-

Sortie Clavier
using System; public class Example { public static void Main() { string line; Console.WriteLine("Enter one or more lines of text (press CTRL+Z to exit):"); Console.WriteLine(); do { Console.Write(" "); Console.WriteLine(" } while (line != null); " + line);

line = Console.ReadLine();
if (line != null)

} } // The following displays possible output from this example: // Enter one or more lines of text (press CTRL+Z to exit): // // This is line #1. // This is line #1. // This is line #2 // This is line #2 // ^Z

Les diffrentes structures de bases


Oprateurs

Bit Bit Soient i et j deux entiers. i<<n dcale i de n bits sur la gauche. Les bits entrants sont des zros. i>>n dcale i de n bits sur la droite. Si i est un entier sign (signed char, int, long) le bit de signe est prserv. i & j fait le ET logique de i et j bit bit. i | j fait le OU logique de i et j bit bit. ~i complmente i 1

1. short i = 100, j = -13; 2. ushort k = 0xF123; 3. Console.WriteLine("i=0x{0:x4}, j=0x{1:x4}, k=0x{2:x4}", i,j,k); 4. Console.WriteLine("i<<4=0x{0:x4}, i>>4=0x{1:x4},k>>4=0x{2:x4},i&j=0x{3:x4},i| j=0x{4:x4},~i=0x{5:x4},j<<2=0x{6:x4},j>>2=0x{7:x4}", i << 4, i >> 4, k >> 4, (short)(i & j), (short)(i | j), (short)(~i), (short)(j << 2), (short)(j >> 2));

le format {0:x4} affiche le paramtre n 0 au format hexadcimal (x) avec 4 caractres (4).

Logique: Idem langage C <, <=, ==, !=, >, >=

Arithmtique Idem langage C + ,-,\,% Utilisation de la classe Math : exemple de mthode accesible double Sqrt(double x) racine carre double Cos(double x) Cosinus double Sin(double x) Sinus double Tan(double x) Tangente double Pow(double x,double y) x la puissance y (x>0) double Exp(double x) Exponentielle double Log(double x) Logarithme nprien double Abs(double x) valeur absolue boolens Idem langage C

double x, y=4; x=Math.Sqrt(y);

-9-

Structure de choix

simple syntaxe : if (condition) {actions_condition_vraie;} else {actions_condition_fausse;}

cas multiples switch(expression) { case v1:actions1; break; case v2: actions2; break; default:actions_sinon;

Structure de rptition

Identique au C for do/while while Structure foreach La syntaxe est la suivante : foreach (Type variable in collection) {instructions; } Notes collection est une collection d'objets numrable. La collection d'objets numrable que nous connaissons dj est le tableau (notion de collection et de conteneur developpe + loin dans le poly) Type est le type des objets de la collection. Pour un tableau, ce serait le type des lments du tableau variable est une variable locale la boucle qui va prendre successivement pour valeur, toutes les valeurs de la collection. Ainsi le code suivant : 1. string[] amis = { "paul", "hlne", "jacques", "sylvie" }; 2. foreach (string nom in amis) { 3. Console.WriteLine(nom); 4. } afficherait : paul hlne jacques sylvie

Chaine de caractre
Codage d'un caractre

Un ordinateur ne comprenant que des valeurs numriques il est ncessaire d'associer chaque symbole reprsentant un caractre (lettre de l'alphaphet, symbole mathmatique, musical etc) une valeur. Cette association symbole/valeur est appel codage. Ci aprs les codages les plus usuels: - ASCII o Le plus ancien. Permet de coder 128 symboles correspondant aux claviers US. 1 symboles= 1 octet - Code Page OEM o Extension du code ASCII sur 256 octets pour tenir compte des langues europennes - GB18030 o Standart pour les applications dveloppes en Chine - Unicode o Organisation en 17 pages contenant 65536 codes possibles(1Mga codes possibles!) o La page 0 est appele " Basic Multilingual Plane" permettant de coder tous les langages modernes o 4 variantes de codages dont: UTF8 : le plus utilis pour les fichiers textes et internet. Codage variable de 1 4 octets Les 127 premiers codes sont ceux de l'ASCII ( d'o sa popularit) - 10 -

UTF16: codage sur 2 ou 4 octets Codage par dfaut utilis pour les caractres en C# 1 char = 2 octets => permet de reprsenter le BPM Moins compact que l'UTF8 mais permet une manipulation plus aise des flux de donnes( taille fixe du codage!)

Exemple d'utilisations d'outils pour les conversions:


byte[]utf8Bytes=System.Text.Encoding.UTF8.GetBytes("0123456789"); byte[]utf16Bytes=System.Text.Encoding.Unicode.GetBytes("0123456789");//UnicodecorrespondUTF16 byte[]utf32Bytes=System.Text.Encoding.UTF32.GetBytes("0123456789"); Console.WriteLine(utf8Bytes.Length);//10 Console.WriteLine(utf16Bytes.Length);//20 Console.WriteLine(utf32Bytes.Length);//40 stringoriginal1=System.Text.Encoding.UTF8.GetString(utf8Bytes); stringoriginal2=System.Text.Encoding.Unicode.GetString(utf16Bytes); stringoriginal3=System.Text.Encoding.UTF32.GetString(utf32Bytes); Console.WriteLine(original1);//0123456789 Console.WriteLine(original2);//0123456789 Console.WriteLine(original3);//0123456789

Les chanes de caractres Classe string

La classe string facilite les oprations de manipulations de chaine (abandonnez le char !). Reprsentation dun objet string : String ch1 = "abcdefghijk"; char car = ch1[4] ; // ici la variable car contient la lettre 'e' // pas de /0 la fin !! Extrait des mthodes accessibles

Exemples
string ch; ch = "abcdef" ; string s2,s1="abc" ; s2 = s1+"def"; //-- tests d'galit avec l'oprateur = = if( s2 == "abcdef" ) System.Console.WriteLine ("s2==abcdef"); else System.Console.WriteLine ("s2<>abcdef"); if( s2 == ch ) System.Console.WriteLine ("s2==ch"); else System.Console.WriteLine ("s2<>ch");

String s1 , s2 ="abc" ; char c = 'e' ; s1 = "d" + Convert.ToString ( c) ; Console.WriteLine(chaine{0}, taille{1},s1,S1.lenght)

- 11 -

using System; public class SplitTest { public static void Main() { string words = "This is a list of words, with: a bit of punctuation." string [] split = words.Split(new Char [] {' ', ',', '.', ':'}); foreach (string s in split) if (s.Trim() != "") Console.WriteLine(s);}}}} // The example displays the following output to the console: // This // is // a // list // of // words // with // a // bit // of // punctuation

Les conversions entre char et string

Conversions Char<-> String

1- Char-> String Plusieurs possibilits: Sol1: Transtypage char car = 'r'; string s; s = (string)car; 2- String-> Char Sur un ensemble de caractere string input = "Hello World!"; char[] values = input.ToCharArray();

Sol2: Mthode string.Tostring char car = 'r'; string s; s = Convert.ToString (car);

sur 1 caractre char charVal = 'a'; stringVal = System.Convert.ToString(charVal);

Les Tableaux
Un tableau est une structure de donnes qui contient plusieurs variables du mme type. Les tableaux sont dclars avec un type :
type[] arrayName;

Les exemples suivants crent des tableaux unidimensionnels, multidimensionnels et en escalier : // Declare a single-dimensional array int[] array1 = new int[5]; // Declare and set array element values int[] array2 = new int[] { 1, 3, 5, 7, 9 }; // Alternative syntax int[] array3 = { 1, 2, 3, 4, 5, 6 }; // Declare a two dimensional array int[,] multiDimensionalArray1 = new int[2, 3]; // Declare and set array element values int[,] multiDimensionalArray2 = { { 1, 2, 3 }, { 4, 5, 6 } }; // Declare a jagged array int[][] jaggedArray = new int[6][]; // Set the values of the first array in the jagged array structure jaggedArray[0] = new int[4] { 1, 2, 3, 4 }; - 12 -

Complment sur les tableaux en escalier (jagged array): Les liens sexpriment par des rfrences sur tableau (le contenu dune case est un rfrence qui pointe vers un tableau)

Formatage et conversion des donnes


Certaines instructions permettent de grer des flux dentres/sorties formats permettant ainsi un change dinformation ais entre variable ( lchange ne se fait pas avec le monde extrieur). Un exemple classique de fonction en C est : sprint() et sscanf Les outils en C# sont : Formatage numrique vers string Syntaxe: xxxx.ToString( chaine de formatage)

double MyPos = 19.95 ,MyNeg = -19.95, MyZero = 0.0; string MyString = MyPos.ToString("$#,##0.00;($#,##0.00);Zero"); //$19,95 MyString = MyNeg.ToString("$#,##0.00;($#,##0.00);Zero"); // ($19,95) MyString = MyZero.ToString("$#,##0.00;($#,##0.00);Zero"); // Zero

Formatage string vers numrique chaine -> int : int.Parse(chaine) ou System.Int32.Parse chane -> long : long.Parse(chaine) ou System.Int64.Parse chane -> double : double.Parse(chane) ou System.Double.Parse(chane) chane -> float : float.Parse(chane) ou System.Float.Parse(chane)

String num = "A"; int val = int.Parse(num, NumberStyles.HexNumber); Console.WriteLine("{0} in hex = {1} in decimal.", num, val); // Parse the string, allowing a leading sign, and ignoring leading and trailing white spaces. num = " -45 "; val = int.Parse(num, NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite); Console.WriteLine("'{0}' parsed to an int is '{1}'.", num, val);

- 13 -

Formatage composite numrique + string -> string Syntaxe : String.Format ( paramtre chaine de formatage voir classe Console) string myName = "Fred"; String.Format("Name = {0}, hours = {1:hh}, minutes = {1:mm}", myName, DateTime.Now);

string FormatString=String.Format("{0:dddd MMMM}", DateTime.Now); string FormatString2 = DateTime.Now.ToString("dddd MMMM"); strin g -> string +numrique Ce type de formatage correspond au sscanf du C. La fonction C# nexiste pas en tant que telle et doit tre ralise en fonction des besoins de lutilisateur laide des mthodes : .Split, .Parse .Substring

string[] Command = { "LED1 ON", "TEMP 25", "VIT,G,100" }; char [] separateur={' ',','}; for (int i = 0; i < Command.Length; i++) { string oneCmd = Command[i]; string[] mot = oneCmd.Split(separateur); // affichage des mots foreach (string v in mot) Console.WriteLine(v); // traitement if (mot[0] == "TEMP") { int temp = int.Parse(mot[1]); Console.WriteLine("temp consigne {0}", temp); } } .

- 14 -

TRAVAIL PERSONNEL
Pour faire une pause la fin de votre programme - terminer par exemple par Console.ReadKey(); Exo1 : On souhaite crire un programme C# de rsolution dans R de l'quation du second degr : Ax2 + Bx +C = 0

Ex2 Dans une boucle le prix d'un article hors taxe est saisi. Le calcul du prix TTC sera calcul puis seront affichs le prix final sous forme "monnaie" (2 chiffres aprs virgule, voir formatage) ainsi que le taux de la TVA en pourcent (1 chiffre aprs la virgule). On sortira de la boucle sur une demande de nouveau calcul . Exo 3 Objectif : compter et afficher le nombre de voyelles compte tenu dans une chaine de caractres. Un chaine contenant les voyelles sera utilis : string voyelle=".". Afin de vous aider faites des recherches sur internet pour trouver les mthodes de la classe string pour: - convertir en majuscules - tester si une chaine contient une lettre (ou une sous-chaine) Exo4 Une date sera saisie sous la forme JJ/MM/AAAA (pas de vrification sur la cohrence de la saisie). Les dlimiteurs possibles sont: / et - (exemple:JJ-MM-AAAA est valide) Extraire en utilisant les mthodes de la classe string les diffrents champs de la date saisie et les stocker dans 3 variables de type entier. Pour l'exercice les boucles foreach sont imposes pour balayer vos tableaux).

- 15 -

TP
Exo 1 Coder lalgorithme de tri bulle suivant:

Exo2 :
Ecrire un programme calculant sur 360 degr n points de la fonction sinus . Le paramtre n sera saisi clavier. Les points seront stocks au pralable dans un tableau qui sera par la suite parcouru pour affichage (instruction foreach impose).
i=5 angle=225,0 val=-0,71 i=6 angle=270,0 val=-1,00 i=7 angle=315,0 val=-0,71

Exo 3 Ecrire la mthode static string toBinaryString ( int n ) qui permet de visualiser le code binaire sous forme de chane de caractre dun nombre entier n cod en int. Pour ce faire vous pourrez exploiterez les possibilits de la mthodes Format ( conversion int->hexa) et IndexOf les tableaux suivant
string[]hexToBinDigit={"0000","0001","0010","0011","0100", "0101","0110","0111","1000","1001","1010", "1011","1100","1101","1110","1111"}; stringhexToDecimalDigit="0123456789abcdef";

Exo4 On souhaite crire une application de manipulation interne des bits d'une variable signe sur 32 bits (int). Le but de l'exercice est de construire une famille de mthodes de travail sur un ou plusieurs bits d'une mmoire. La visualisation des rultats se fera l'aide de la mthode toBinaryString prcedemment cre. L'application construire contiendra 9 mthodes :
1. Une mthode BitSET permettant de mettre 1 un bit de rang fix. static int BitSET (int nbr, int num) { .. } 2. Une mthode BitCLR permettant de mettre 0 un bit de rang fix. static int BitCLR (int nbr, int num) { .. } 3. Une mthode BitCHG permettant de remplacer un bit de rang fix par son complment. static int BitCHG (int nbr, int num) { .. } 4. Une mthode SetValBit permettant de modifier un bit de rang fix. static int SetValBit (int nbr, int rang, int val) { .. } 5. Une mthode DecalageD permettant de dcaler les bits d'un entier, sur la droite de n positions(introduction de n zros gauche).
static int DecalageD (int nbr, int n) { .. }

6. Une mthode DecalageG permettant de dcaler les bits d'un entier, sur la gauche de n positions (introduction de n zros droite).
static int DecalageG (int nbr, int n) { .. }

7. Une mthode BitRang renvoyant le bit de rang fix d'un entier. static int BitRang (int nbr, int rang) { .. } 8. Une mthode ROL permettant de dcaler avec rotation, les bits d'un entier, sur la droite de n positions (rintroduction gauche).
static int ROL (int nbr, int n) { .. }

9. Une mthode ROR permettant de dcaler avec rotation, les bits d'un entier, sur la gauche de n positions (rintroduction droite).
static int ROR (int nbr, int n) { .. } Les mthodes ROL et ROR rutiliseront les autres mthodes (rinjection du bit de poids fort sur le faible)

Proposition de squelette de classe C# implanter : class Application8Bits { static void Main(string [ ] args){ .. } static int BitSET (int nbr, int num) { .. } static int BitCLR (int nbr, int num) { .. } . } Observez le codage d'entiers ngatifs. Comment s'appelle ce codage? Quel est l'effet d'un dcalage gauche d'un entier ngatif?Expliquez. - 16 -

NOTION D'OBJET
La complexit du monde rel nous conduit dfinir, classifier, organiser et hirarchiser les diffrents objets qui le composent. Ces objets possdent des proprits et des comportements propres. Une mme famille d'objets, c'est--dire avec des caractristiques communes, peut tre regroupe dans un ensemble appel classe. La programmation oriente objet reprend son compte ces notions d'objet et de classe. Le dveloppeur pourra sa guise crer une classe, dfinissant les caractristiques et les proprits d'une mme famille d'objet. Un objet, c'est--dire un lment particulier d'une classe, est appel instance d'une classe. Exemples : Toutou proprits : ge, poids, couleur comportements : courir, aboyer, manger Etudiant Proprits : Nom, ge Mthodes bavarder, couter, dormir

L'objectif est de faciliter et de fiabiliser l'criture de programmes complexes en dcomposant l'analyse l'aide de diffrentes entits distinctes (classe, objet). Du point de vue interne, l'objet est dcrit en dtail tant au niveau des proprits que de ses mthodes d'action. Du point de vue externe, l'objet est une bote noire accessible au travers d'une certaine interface (les mthodes). Avantages : rutilisation des objets structuration modulaire autonomie des objets maintenance et debuggage facilits

UTILISATION DES CLASSES ET MANIPULATIONS D'OBJETS


Dfinition d'une classe
Une classe permet de regrouper au sein d'une mme structure le format des donnes qui dfinissent l'objet et les fonctions destines manipuler ces objets. On dit qu'une classe permet d'encapsuler les diffrents lments et les fonctions dans un ensemble appel objet. //Version 1 :1 seul fichier using System; Dclaration de la classe class Chat { uint Age; // par dfaut Private!! private uint Poids; public void Miauler() { Console.WriteLine("Miaouuu"); } public void DefAge(uint var) { Age = var; } }

class Program { static void Main(string[] args) { Chat UnMatou; Utilisation UnMatou = new Chat(); de la UnMatou.Miauler(); classe UnMatou.DefAge(10); Console.ReadKey(); } }

Commentaires ge et poids correspondent aux champs de la classe (ie donnes, tat interne) Miauler et DefAge correspondent une mthode de la classe. Le mot-cl public permet de signifier que les mthodes ou proprits sont accessibles de l'extrieur. Le mot-cl private permet de signifier que les donnes ne sont accessibles que par les mthodes appartenant la classe (non accessible de lextrieur directement). Chat UnMatou; cre une rference sur Chat - 17 -

UnMatou = new Chat(); cre une instance de Chat (ou objet de type de Chat) UnMatou.Age=10 ; ne compile pas car Age est private donc inacessible de lextrieur !

// version 2 : 2 fichiers using System; using ProjetChat; class Program { static void Main(string[] args) { Chat UnMatou; UnMatou = new Chat(); UnMatou.Miauler(); UnMatou.DefAge(10); Console.ReadKey(); } } using System;

namespace ProjetChat { public class Chat { uint Age; // par Private!! private uint Poids;

dfaut

public void Miauler() { Console.WriteLine("Miaouuu"); } public void DefAge(uint var) { Age = var; } } }

Commentaires : La classe est livre dans un fichier spar pour une meilleure lisibilit Lespace de nommage tant diffrent, la clause using ProjetChat est utilise pour la visibilit de la classe Chat De manire gnrale et pour des raisons de scurit les champs sont maintenus private et les mthodes publiques. De cette manire, en cas de problme sur un objet, seules les mthodes appartenant la classe incrimine peuvent tre mises en cause puisque ce sont les seules qui puissent accder aux donnes.

Cration et vie des objets


Loprateur new permet de crer les objets qui seront stocks en RAM. La rfrence renvoye sert initialiser la rfrence utilisateur pour la manipulation des objets : Chat Matou1,Matou2; // 2 rfrence nulles ( non initialises) Matou1= new Chat(); Matou2= new Chat(); . Matou1=new Chat(); // Matou1 fait rfrence a un 3me chat! Chaque objet en mmoire possde ses propres proprits Age et Poids; Au moment de la cration de l'objet, une mthode spciale, le constructeur, est appele. Ce mcanisme rpond la question : comment crer et initialiser lobjet. Un constructeur par dfaut existe : exemple dappel new Chat(); La fin de vie de lobjet est dcide par le ramasse-miette qui dsalloue lespace mmoire. Il en rsulte que ,non contrl par lutilisateur, ce mcanisme est non dterministe ( ne convient pas pour des systmes temps rels au sens strict).

- 18 -

Mise en oeuvre des mthodes des classes


Principe

Les mthodes des classes ne sont ni plus ni moins que des fonctions qui permettent : de dfinir certains comportements des objets d'accder (interface publique) et de manipuler les champs attributs des objets Les mthodes sont appeles au travers dun objet : UnMatou.Miauler(); Lors de lappel dune mthode une rfrence surlobjet courant (dans lexemple UnMatou) est transmise implicitement par le biais d'un mot cl :this. Exemple : appel de la mthode: UnMatou.SetPoids(5);
class Chat { uint Poids .. public void setPoids (uint Poids) { Poids = Poids; } } Commentaire : Il y a ambiguit entre Poids variable locale transmise lors de lappel et Poids proprit de la Class class Chat { uint Poids .. public void setPoids (uint Poids) { this.Poids = Poids; } } Commentaire : This :objet courant ( UnMatou) This.Poids : accs la variable lobjet courant (UnMatou)

Poids

de

Solution: emploi de this


Passage dargument

Passage par valeur


Si un paramtre est dclar pour une mthode sans ref ni out le passage se fait par valeur : une variable ou une rfrence locale est cre puis la valeur recopie. class Program { static void Method(string s2, MonInt test2, int varlocal) { s2 = "changed"; test2.vartest = 10; varlocal = 10; Testint est une classe donc testint est une } rfrence. public class MonInt { public int vartest=5; } static void Main(string[] args) { string str = "original"; MonInt testint = new MonInt(); int var = 5; Method(str,testint,var); Console.WriteLine(str); //"original"; Console.WriteLine(testint.vartest);// 10 Console.WriteLine(var);// 5 Console.ReadKey(); }

Test2 est une copie locale de la rfrence (mais pas de lobjet) test2.vartest = 10; modifie la case mmoire var est cre dans la pile ( objet valeur) varlocal est une copie locale=> pas de modification de var Le cas string est part puisque bien que str soit une rfrence il y cration dun nouvel espace mmoire et recopie du contenu point par str. La classe string est dite immuable (en anglais immutable)=> une fois initialis par son constructeur toute modification entrane un nouvel objet de type string

REMARQUE :Un tableau est toujours dsign par sa rfrence et est allou par new (mme si ce new napparat pas quand un tableau est cr et initialis dans la foule). Cest ce moment que la vritable zone de donnes du tableau est alloue. La rfrence pointe alors sur cette zone.

- 19 -

EN RESUME: UN PASSAGE PAR VALEUR CREE UNE COPIE TEMPORAIRE PAR CLONAGE: dans le cas d'un type 'value' : copie d'un objet temporaire ayant mme valeur; dans le cas d'un type rfrence: clonage des rfrences => il n'y pas cration d'un nouvel objet! Mme si le mcanisme de passage s'est fait par valeur , du point de vue de l'objet, le passage s'est fait "par rfrence"

Passage par rfrence Mot cl ref


Le mot cl ref fait en sorte que les arguments soient passs par rfrence. La consquence est que toute modification apporte au paramtre dans la mthode est reflte dans cette variable lorsque la mthode appelante rcupre le contrle. Pour utiliser un paramtre ref, l'appelant et l'appel doivent tous deux utiliser le mot cl ref explicitement. Par exemple :

classRefExample1 { staticvoidMethod(refinti) { i=44; } staticvoidMain() { intval=0; Method(refval); //valisnow44 } }

classRefRefExample2 { staticvoidMethod(refstrings) { s="changed"; } staticvoidMain() { stringstr="original"; Method(refstr); //strisnow"changed" }

Mot cl out Le mot cl out fait en sorte que les arguments soient passs par rfrence. Il est semblable au mot cl ref, mais ref ncessite que la variable soit initialise avant d'tre passe. Pour utiliser un paramtre out, la dfinition de mthode et la mthode d'appel doivent toutes deux utiliser le mot cl out explicitement. Par exemple :
ClassOutExample1 { staticvoidMethod(outinti) { i=44; } staticvoidMain() { intvalue; Method(outvalue); //valueisnow44 } } classOutReturnExample2 { staticvoidMethod(outinti,outstrings1,outstrings2) { i=44; s1="I'vebeenreturned"; s2=null; } staticvoidMain() { intvalue; stringstr1,str2; Method(outvalue,outstr1,outstr2); //valueisnow44 //str1isnow"I'vebeenreturned" //str2is(still)null]}

- 20 -

Accs aux proprits


Par les raisons dj voques prcdemment les proprits des classes seront dclare private. Un accs direct dans votre programme est interdit : UnMatou.Poids=10. Des interfaces daccs, nommes acesseurs (getter/setter in english) sont donc ncessaires pour des lectures/critures simples. Deux faons de procder sont possibles :

1- acceseurs standarts
using System; public class Chat { uint Age; // par dfaut Private!!

2- Proprits
using System; public class Chat { uint Age; // par dfaut Private!!

public void Miauler() { Console.WriteLine("Miaouuu"); } // Accesseurs public void SetAge(uint var) { this.Age = var; } public uint GetAge() { return (this.Age); } } class Program { static void Main(string[] args) { Chat UnMatou= new Chat(); UnMatou.SetAge(10); Console.WriteLine("le matou UnMatou.GetAge()+" ans"); Console.ReadKey(); }

"

Les proprits sont des membres offrant un mcanisme souple pour la lecture, l'criture ou le calcul des valeurs de champs privs. Elles peuvent tre utilises comme si elles taient des membres de donnes publiques, mais en fait, ce sont des mthodes spciales appeles accesseurs. Elles facilitent l'accs aux donnes tout en prservant la scurit et la souplesse des mthodes Avec des proprits, une classe peut exposer de manire publique l'obtention et la dfinition de valeurs, tout en masquant le code d'implmentation ou de vrification. Un accesseur de proprit get permet de retourner la valeur de proprit, et un accesseur set est utilis pour assigner une nouvelle valeur. Ces accesseurs peuvent avoir des niveaux d'accs diffrents. Pour plus d'informations, consultez Accessibilit de l'accesseur asymtrique (Guide de programmation C#). Le mot cl value sert dfinir la valeur assigne par l'indexeur set. Les proprits qui n'implmentent pas de mthode set sont en lecture seule. }

public void Miauler() { Console.WriteLine("Miaouuu"); } // Proprits :get/set public uint AgeChat { get { return this.Age; } set { if (value < 0 || value > 30) { throw new Exception("Age du Chat (" + value + ") invalide"); } else { + this.Age = value; } } } } class Program { static void Main(string[] args) { Chat UnMatou= new Chat(); UnMatou.AgeChat=10; Console.WriteLine("le matou UnMatou.AgeChat+" ans"); //try-catch try {UnMatou.AgeChat = 35; } catch (Exception ex) { Console.Error.WriteLine(ex.Message); } Console.ReadKey(); }

"

Remarque: La plupart des cas les "get et set" se bornent des lectures/critures simples. Le C# 3 introduit les proprits automatiques ( dconseiller pour dbuter). Ex: ClassMaClasseDemo
{publicintage{get;set;}//Ilacrationautomatiqued'unchampprivcorrespondantl'age publicstringnom{get;set}//Ilacrationautomatiqued'unchampprivcorrespondantaunom }

- 21 -

Mthodes et champs statiques

Les Mthodes et champs statiques ne s'appellent pas au travers d'un objet comme les exemples prcdents mais partir de leur classe d'objet: Mthode d'instance MaClassObjet Objet1; Objet1.MaMethode; Mthode statique MaClassObjet.UneAutreMethode

Ci aprs des exemples de mthodes statiques dj manipules: Console.WriteLine() o WriteLine est la mthode statique de la classe Console. String.Parse()o Parse est la mthode statique de la classe string L'attribut statique devant un champ d'une classe indique que la donne ( la variable) conserve sa valeur sur les diffrentes instances de la classe. Nous pouvons dire en quelque sorte que cette donne sera partage entre les diffrents objets issus de la mme classe. Cette facilit permet notamment de compter le nombre d'instance d'une classe (ie nombre d'objets) et par exemple de contrler une population donne ou le nombre d'accs une ressource. Pour l'exemple suivant reportez vous au chapitre suivant sur les constructeurs:
usingSystem; usingSystem.Text; namespaceConsoleApplication1 { publicclassImprimante {//champs privatestaticuintnombreImprimantes; privatestringimprimanteNom; privateintnumeroSalle; //accesseurs(get/set) publicstringImprimanteNom //notezlamajuscule //quidiffrencielechamp //delaproprit {get{return(imprimanteNom);} set{imprimanteNom=value;} } publicintNumeroSalle {get{return(numeroSalle);} set{numeroSalle=value;} } //Constructeur publicImprimante(stringname,intnum) { nombreImprimantes++;//incrementenbre totalimprimante imprimanteNom=name;//miseajour champnom numeroSalle=num;//miseajour numerosalle } //methodestatique publicstaticuint AfficheTotalImprimateGEII() { Console.WriteLine("lenombretotalest:" +nombreImprimantes); return(nombreImprimantes); } //surchagedelamethodeToStringpource decrire publicoverridestringToString() { Console.WriteLine("imprimante{0} localiseensalle{1}",imprimanteNom,numeroSalle); returnbase.ToString(); } } classProgram { staticvoidMain(string[]args) { Imprimantebrother=new Imprimante("brother",215); Imprimantehp=newImprimante("HP", 208); Imprimantehp2=newImprimante("HP", 214); brother.ToString(); hp.ToString(); Console.WriteLine("sallepourhp2:"+ hp2.NumeroSalle); uint totalAtelier=Imprimante.AfficheTotalImprimateGEII(); Console.ReadKey(); } } }

Rsultat cran imprimante brother localise en salle 215 imprimante HP localise en salle 208 salle pour hp2: 214 le nombre total est:3

- 22 -

constructeur
dclaration de constructeur

Dans tout programme le dveloppeur doit se proccuper de l'initialisation des objets crs. Il peut comme dans les cas prcdents incorpors des mthodes spcifiques. Cependant le langage C++ inclut une fonction membre spciale appele constructeur. Cette mthode, du mme nom que la classe, est appele automatiquement au moment de la cration d'un objet. De la mme manire, au moment de la destruction de cet objet, une fonction spciale du nom de la classe mais prcd dun tilde ~, est invoqu.

using System; class Chat dclaration de la classe { // proprit automatique (private) // avec avec acceseur public //compatible C# 3 public ushort age { get; set; } public string nom { get; set; } // constructeur public Chat(ushort initialAge) { age=initialAge;} // destructeur (finalyser) ~Chat() {Console.WriteLine("chat dtruit");} // dbut

// paramtres : Aucun // rle : imprime "Miaou" l'cran public void Miauler() { Console.WriteLine("Miaou.."); } } class Program { static void Main(string[] args) { Chat Frisky=new Chat(5); // au moment de la cration le constructeur est //automatiquement appel Frisky.Miauler(); Console.WriteLine( "Frisky est un chat qui a " +Frisky.age+" ans"); Frisky.age=7; Console.WriteLine( "Maintenant Frisky a " +Frisky.age+" ans"); ; Console.ReadKey(); } }

// dfinition de la mthode Miauler // renvoie : void

Surcharge de constructeur

Si un constructeur avec argument a t dfini alors la dclaration d'objet non initialis est impossible : dans l'exemple prcdent : Chat Frisky ; gnrerait une erreur. Alors que : Chat Frisky(5); est autoris. Solution : utiliser le mcanisme de surcharge de fonction. C'est dire, crire les diffrents constructeurs qui correspondent au diffrent cas de figure des initialisations souhaites. Ci-aprs un exemple de surchage du constructeur Chat.
using System; class Chat dclaration de la classe { // dbut // dfinition de la mthode Miauler // renvoie : void // paramtres : Aucun // rle : imprime "Miaou" l'cran public void Miauler() { Console.WriteLine("Miaou.."); } }

class Program { static void Main(string[] args) { Chat [] TabChat=new Chat[3]; // constructeurs TabChat[0] = new Chat(); public Chat(ushort initialAge) TabChat[1] = new Chat(10); { age=initialAge;} TabChat[2] = new Chat(10,"frisky"); // au moment de la cration le public Chat() // structeur estautomatiquement appel { age = 0; } TabChat[2].Miauler(); public Chat(ushort initialAge,string Console.WriteLine("Ce chat est un chat qui a " + TabChat[2].age + " ans"); nom) TabChat[2].age = 7; { age = initialAge; this.nom = nom; } Console.WriteLine("CE chat a " + TabChat[2].age + " ans"); // destructeur (finalyser) Console.WriteLine("Il s'appelle " + TabChat[1].nom); ~Chat() Console.ReadKey(); {Console.WriteLine("chat dtruit");} } }

// proprit automatique (private) // avec avec acceseur public //compatible C# 3 public ushort age { get; set; } public string nom { get; set; }

- 23 -

TRAVAIL PERSONNEL
1- Avant de tester ce programme pronostiquer l'affichage?(en justifiant!!)Le saisir et vrifier en pas pas.
namespaceConsoleApplication1 { classMonInt { publicintval{get;set;} } classProgram { staticvoidMain(string[]args) { MonIntrefUnInt=newMonInt(); intx=3; refUnInt.val=10; fct(x,refUnInt); Console.WriteLine("x:{0}val: {1}",x,refUnInt.val); Console.ReadLine(); } staticvoidfct(inty,MonInttest) { test.val=20; y=30; } } }

2- Modifier (en faisant un nouveau projet) le programme prcdent de telle manire raliser un passage par rfrence sur la variable x initialise. Conclusion. Refaire maintenant sur x non initialise.Apporter les modifications pour que cela fonctionne. 3- Soit le programme suivant

namespaceConsoleApplication1 { classProgram { staticvoidMain(string[]args) { int[]tab=............... fct(tab); foreach(.) Console.WriteLine(.); Console.ReadKey(); } staticvoidfct(int[]tab2) { //ajouter1chaquelement } }

Avant saisie: - Le contenu du tableau sera-t-il modifi? - Peut-on supprimer le tableau (tab2=null) dans la fonction? - Peut-on faire 'repointer' tab vers un nouveau tableau qui aurait t cre dans la fonction? - Peut-on redimmensionner tab dans la fonction ? Array.Resize(ref tab2, 3); Vrifier vos rponses en faisant du pas pas.

4- Mme travail que prcdemment mais le passage se fera par rfrence? 5-Crer une classe ville
ExoVille est l'espace de nommage (namespace) CompareVille compare 2 villes (nom et population identique) Un argument de type Ville en entre Un rsultat en sortie de type bool (boolen) A faire en TP: ToString est la rcriture de la mthode ToString (voir exemple dans ce chapitre). Cette fonction renvoie un string . Vous utiliserez string.format pour raliser dans le "main" un affichage du type: Ville Toulon , population 128000, maire Falco

Le programme principal sera simple et mettra en uvre la classe Ville Cration des objets " la main" (pas de console.read) l'aide des diffrents constructeurs Affichage des diffrents champs Tester CompareVille 6- faire des recherches sur internet pour comprendre les notions suivantes (important pour votre TP): multitches, processus, thread, ordonnancement ( - 24 -

TP
1. Reprendre la classe Ville du travail personnel 1-1 Ecrire ToString. Tester avec une ville (publicoverridestringToString(){//codeici=} 1-2 Crer ' la main' un tableau de 5 villes. Raliser l'affichage l'aide d'une boucle. 1-3 Rajouter une mthode statique CompareVille avec 2 arguments ville1 et ville2.Tester. 1-4 Rajouter la mthode d'instance
publicvoidAdditionnePopulation(VillenomVille2,?????uintresultat)

Cette mthode doit pouvoir s'utiliser avec une variable non initialise . Par quoi faut-il remplacer ???? pour que le rsultat soit l'argument de sortie. Tester. 2. Envoi de mail 2.1. Installez ArgoSoft Paramtrer le DNS local : par exemple @geii.fr et @iut-geii.fr Crer des utilisateurs 2.2. examiner sur msdn en ligne la classe SmtpClient et MailMessage Ecrire le programme le plus simple possible (pas de mthodes asynchrones!) pour envoyer un mail Lancer outlook express (Dmarrer>xcuter>msimn.exe). Paramtrer les comptes (127.0.0.1) et vrifier les mails reus En utilisant la classe Attachment joindre en pice jointe un fichier image (bmp ou jpg) 4. Premire application graphique :IHM d'envoi de mail

Pour ce faire vous utiliserez les classes TextBox,ButtonetComboBox. Dans un premier temps tous les objets seront placs de manire statique sur le formulaire avec la bote outils de Visual Studio. Pour rcuprer la valeur d'une comboBox vous pouvez faire: stringto=ComboBoxDestinataire.Text;avecComboBoxDestinatairedutypecomboBox o stringto=(string)ComboBoxDestinataire.SelectedItem Dans un deuxime temps les deux comboCox seront places (cres) de manire dynamique au moment de l'initialisation du formulaire (ie appel du constructeur):
publicpartialclassForm1:Form {//user privateComboBoxComboBoxDestinataire; privateComboBoxComboBoxCopieCC; privatestring[]annuaire; publicForm1() { InitializeComponent(); annuaire=newstring[]{"","oscar@geii.fr","test@geii.fr","amel@iutgeii.fr"}; ComboBoxDestinataire=newComboBox(); ComboBoxDestinataire.Location=newPoint(this.textBoxMessage.Location.X,this.labelTo.Location.Y); ComboBoxDestinataire.Items.AddRange(annuaire); this.Controls.Add(ComboBoxDestinataire);

- 25 -

CLASSES COURANTES UTILISEES


Les cultures
Nous avons vu qu'il tait possible d'utiliser des formateurs standards pour spcifier le rsultat d'un l'affichage Le C# fournit 3 classes permettant d'obtenir un contrle plus personnalis des donnes manipules: - CultureInfo - NumberFormatInfo - DateTimeFormatInfo

Classe CultureInfo

La classe CultureInfo (using System.Globalization;) rend des informations spcifiques une culture, par exemple la langue, la sous-langue, le pays et/ou la rgion ou le calendrier associ la culture, ainsi que les conventions applicables cette dernire. Voici des exemples concrets de diffrences rencontres en fonction de la nationalit de l'utilisateur: les Anglo-Saxons reprsentent les dates en intervertissant les jours et mois: MM/JJ/AA certains pays privilgient le point . au lieu de la , comme sparateur de la partie fractionnaire : 13.5 ou 13,5 pour manipuler la monnaie le symbole reprsentant la devise varie en fonction des pays. Culture localis dans l'application: classe CultureInfo
//pbd'affichagedeenmodeconsole //sol:passerenLucidaconsole //changerl'encodagedelaconsoleenUTF8(reprsentationUnicode Console.OutputEncoding=Encoding.UTF8; ////////////////////////////// CultureInfoculture_courante=CultureInfo.CurrentUICulture;//methodestatique:retourneculturecourante Console.WriteLine("culturecourante"+culture_courante.DisplayName); decimalprix=12.3M; CultureInfoci_US=newCultureInfo("enUS");//nvlobjetcultureUSA stringtext_prix_US=prix.ToString("c",ci_US); Console.WriteLine(ci_US.DisplayName+":"); Console.WriteLine(text_prix_US); CultureInfoci_Es=newCultureInfo("esEs",false);//nvlobjetcultureEspagnole stringtext_prix_Es=string.Format("{0:c}",ci_Es);//varianteau.ToString Console.Write(ci_Es.DisplayName+":"); culture courante Franais Console.WriteLine(text_prix_Es); (France) Thread.CurrentThread.CurrentCulture=newCultureInfo("enGB");// Anglais (tats-Unis): stringtext_prix=prix.ToString("c"); $12.30 Console.WriteLine(text_prix); Espagnol (Espagne): es-ES Console.ReadKey(); 12.30

Culture globalise pour l'application


usingSystem.Globalization; usingSystem.Threading; ..... Thread.CurrentThread.CurrentCulture=newCultureInfo("enUS"); doubled=1.23; strings=d.ToString();//scontient1.23 s=d.ToString("C");//scontient$1.23

Classe NumberFormatInfo

Cette classe permet de personnaliser le formatage des nombres Exemple 1: Accepte le . ou , comme sparateur de partie dcimale
Console.WriteLine("PrixHTsvp:"); stringchainePrixHT=Console.ReadLine(); if(chainePrixHT.Contains(".")) { Varf=newSystem.Globalization.NumberFormatInfo(); f.NumberDecimalSeparator="."; prixHT=double.Parse(chainePrixHT,f); } else prixHT=double.Parse(chainePrixHT); Exemple2:Changementdusymbolededevise . NumberFormatInfof=newNumberFormatInfo(); f.CurrencySymbol="$$"; Console.WriteLine(3.ToString("C",f));//$$ 3.00
.

- 26 -

Classe DateTimeFormatInfo

Cette classe permet d'obtenir des formatages spcifiques des dates (en plus des formateurs prdfinis par le C# avec la mthode .ToString voir classes dates plus loin dans le poly) Exemple 1
//creationparexempled'unnvlDateTimeFormatInfopartirdel'original //nepasfaireDateTimeFormatInfomydateformat=ciFr.DateTimeFormatcarjustenouvellereferencesurlememe objet! DateTimeFormatInfomydateformat=(DateTimeFormatInfo)ciFr.DateTimeFormat.Clone();//creationd'unnvl objet! string[]jourSemaine={"L","Mar","Mer","Jeud","V","S","D"}; mydateformat.AbbreviatedDayNames=jourSemaine; string[]jourSemaineOrigine=ciFr.DateTimeFormat.AbbreviatedDayNames; temps actuel :13/10/2010 10:59:01 foreach(stringjourinjourSemaineOrigine)Console.Write(jour); temps actuel culture modifie :13-10-2010 10:59:01 Console.WriteLine("tempsactuel:"+datenow.ToString("ddd")); Console.WriteLine("tempsactuel:"+datenow.ToString("ddd",mydateformat));

Exemple 2
CultureInfociFr=newCultureInfo("frFR");

//nepasfaireDateTimeFormatInfomydateformat=ciFr.DateTimeFormatcarjustenouvellereferencesurlememe objet! DateTimeFormatInfomydateformat=(DateTimeFormatInfo)ciFr.DateTimeFormat.Clone();//creationd'unnvl objet! string[]jourSemaine={"D","L","Ma","Me","Jeud","V","S"}; Affichage jour d'origine abrg mydateformat.AbbreviatedDayNames=jourSemaine; dim. lun. mar. mer. jeu. ven. string[]jourSemaineOrigine=ciFr.DateTimeFormat.AbbreviatedDayNames; sam. Console.WriteLine("Affichagejourd'origineabrg"); temps actuel:mer. foreach(stringjourinjourSemaineOrigine)Console.Write(jour+""); temps actuel:Me DateTimedatenow=DateTime.Now; Console.WriteLine("\ntempsactuel:"+datenow.ToString("ddd")); Console.WriteLine("tempsactuel:"+datenow.ToString("ddd",mydateformat)); Console.ReadKey();

- 27 -

Le Temps s et les da ates


Type TimeSpa an

Un objet TimeSpan reprs sente un inter rvalle de temp ps, ou une du ure, mesur en nombre positif p ou nga atif de d jours, heures, minutes, secondes et fractions de seconde La valeur d'un n objet TimeS Span est le nombre de gra aduations qu uivalant l'int tervalle de tem mps reprsen nt. Une graduatio on est gale 100 nanose econdes. ATTENTION: A : TimeSpan est e une struc cture, donc d du type valeu ur! Les L construc cteurs
TimeSpan (Int64) TimeSpan (Int32, In nt32, Int32) TimeSpan (Int32, In nt32, Int32, Int32) TimeSpan (Int32, In nt32, Int32, Int32, Int32) Initialise un nouv veau TimeSpan ave ec le nombre de graduations spcifi. Pris en charge pa ar le .NET Compact Framework. Initialise un nouv veau TimeSpan par r rapport un nom mbre d'heures, de m minutes et de secondes spcifi. Pris en charge pa ar le .NET Compact Framework. Initialise un nouv veau TimeSpan par r rapport un nom mbre de jours, d'heu ures, de minutes et de secondes spcifi. Pris en charge pa ar le .NET Compact Framework. Initialise un nouv veau TimeSpan par r rapport un nom mbre de jours, d'heu ures, de minutes, de e secondes et de millisecondes sp cifi. Pris en charge pa ar le .NET Compact Framework.

Les L Proprit s
Days Obtient le nombre de jours enti iers reprsents par la structure TimeSpan T actuel lle. Hours Obtient le nombre d'heures ent tires reprsentes par la structur re TimeSpan act tuelle. Milliseconds Obtient le nombre de millisecon ndes entires rep prsentes par la a structure TimeS Span actuelle. Minutes Obtient le nombre de minutes entires e reprsen ntes par la struc cture TimeSpan e en cours. Seconds S Obtient le nombre de secondes s entires reprse entes par la stru ucture TimeSpan n en cours. Ticks T Obtient le nombre de graduatio ons reprsentant la valeur de la st tructure TimeSp pan en cours. TotalDays T Obtient la valeu ur de la structure e TimeSpan expr rime en jours en ntiers et fractionn naires. TotalHours T Obtient la valeu ur de la structure e TimeSpan expr rime en heures entires et fractio onnaires. TotalMillisecond T s Obtient la valeu ur de la structure e TimeSpan expr rime en millisecondes entires et e fractionnaires. TotalMinutes T TotalSeconds Obtient la valeu ur de la structure e TimeSpan expr rime en minutes s entires et fract tionnaires. Obtient la valeu ur de la structure e TimeSpan expr rime en secondes entires et fra actionnaires.

Des D Mthode es
Static FromDays s S S S S FromHours Retourn ne un TimeSpan reprsentant un nombre de jours s spcifi, o la s spcification est prcise la milliseconde prs. Retourn ne un TimeSpan n reprsentant un n nombre d'heure es spcifi, o la a spcification es st prcise la milliseconde prs. ne un TimeSpan n reprsentant un n nombre spcifi de milliseconde es. FromMillis seconds Retourn FromMinu utes FromSeco onds Add Subtract TryParse Retourn ne un TimeSpan n reprsentant un n nombre de minutes spcifi, o la spcification est prcise la milliseconde prs. Retourn ne un TimeSpan n reprsentant un n nombre de sec condes spcifi, o o la spcificatio on est prcise la a milliseconde prs. Ajoute le TimeSpan sp cifi cette insta ance. Soustra ait le TimeSpan spcifi s de cette instance. Constru uit un nouvel obje et TimeSpan partir d'un intervalle de temps sp cifi dans une ch hane de caract res. Les par ramtres spcifie ent l'intervalle de temps et la varia able dans laquelle le nouvel obje et TimeSpan est retourn .

Exemples
Console.WriteLine (new TimeSpan (2, 30, 0)); // 02:30:00 Console.WriteLine (TimeSpan.FromHours (2.5)); // 02:30:00 Console.WriteLine (TimeSpan.FromHours (2.5)); // 02:30:00 TimeSpan nearlyTenDays =TimeSpan.FromDays(10) - TimeSpan.FromSeconds(1); // 9.23:59:59 Console.WriteLine (nearlyTenDays.Days); // 9 Console.WriteLine (nearlyTenDays.Hours); // 23 Console.WriteLine (nearlyTenDays.Minutes); // 59 Console.WriteLine (nearlyTenDays.TotalDays); // 9.99998842592593 Console.WriteLine (nearlyTenDays.TotalHours); // 239.999722222222

Type DateTime

Le type valeur DateTime reprsente des dates et des heures. Les valeurs de date sont mesures en units de 100 nanosecondes, appeles graduations, et une date spcifique correspond au nombre de graduations coules compter de 12:00 (minuit), le 1er janvier de l'anne 0001 aprs J.C. de l're commune dans le calendrier GregorianCalendar. Par exemple, une valeur de graduations gale 31241376000000000L reprsente la date du vendredi 1er janvier 0100 12:00:00 (minuit). Une valeur DateTime est toujours exprime dans le contexte d'un calendrier explicite ou par dfaut. Avec le type DateTime il est possible de reprsenter une date dans un rpre: - locale: lie l'horloge de votre ordinateur (horloge windows) - UTC (Coordinated Universal Time): heure universelle ( anciennement Greenweech) o Le temps universel coordonn est l'heure mesure la longitude zro, le point de dpart de l'UTC. L'heure d't ne s'applique pas l'UTC. - Non spcifi

Constructeurs
DateTime (Int64, DateTimeKind) Initialise une nouvelle instance de la structure DateTime avec un nombre spcifi de graduations et une heure UTC ou locale. Pris en charge par le .NET Compact Framework. Initialise une nouvelle instance de la structure DateTime avec l'anne, le mois et le jour spcifis. Pris en charge par le .NET Compact Framework. Initialise une nouvelle instance de la structure DateTime avec l'anne, le mois et le jour spcifis pour le calendrier spcifi. Pris en charge par le .NET Compact Framework. Initialise une nouvelle instance de la structure DateTime avec l'anne, le mois, le jour, la minute et la seconde spcifis. Pris en charge par le .NET Compact Framework. Initialise une nouvelle instance de la structure DateTime avec l'anne, le mois, le jour, la minute et la seconde spcifis pour le calendrier spcifi. Pris en charge par le .NET Compact Framework. Initialise une nouvelle instance de la structure DateTime avec l'anne, le mois, le jour, l'heure, la minute, la seconde, et l'heure UTC ou locale. Pris en charge par le .NET Compact Framework.

DateTime (Int32, Int32, Int32)

DateTime (Int32, Int32, Int32, Calendar)

DateTime (Int32, Int32, Int32, Int32, Int32, Int32) DateTime (Int32, Int32, Int32, Int32, Int32, Int32, Calendar) DateTime (Int32, Int32, Int32, Int32, Int32, Int32, DateTimeKind)

Exemple:
DateTimedt1=newDateTime(2008,10,2,23,3,59,10,DateTimeKind.Utc); DateTimedt2=newDateTime(2008,10,2,newSystem.Globalization.JapaneseCalendar()); Console.WriteLine("date:{0}",dt1); Console.WriteLine("date:{0}",dt2); Console.WriteLine(dt2.Kind); Ci-aprs quelques mthodes (liste non exhaustive voir msdn en ligne pour complments d'infos).

- 29 -

Nom Add AddDays AddHours AddMinutes s AddMonths s AddYears Compare DaysInMont th Equals

Descrip ption Ajoute la a valeur du TimeSpan spcifi la valeur de cette e instance. Ajoute le e nombre de jours spcifi la va aleur de cette ins stance. Ajoute le e nombre d'heur res spcifi la valeur v de cette instance. Ajoute le e nombre de min nutes spcifi la a valeur de cette e instance. Ajoute le e nombre de mo ois spcifi la va aleur de cette ins stance. Ajoute le e nombre d'ann es spcifi la v valeur de cette in nstance. Compare deux instances s de DateTime et retourne une ind dication de leurs valeurs relatives s. Retourne le nombre de jours compris dans le mois et l'an nne spcifis. Surcharg g. Retourne une e valeur indiquan nt si deux objets DateTime, ou si une instance Da ateTime et un au utre objet ou u DateTime sont gaux. Ajoute un u intervalle de te emps spcifi u une date et une heure h spcifies, gnrant une no ouvelle date et heure. Dtermine si deux instan nces spcifies de e DateTime sont t gales. Dtermine si un DateTim me spcifi est su uprieur un aut tre DateTime spcifi. Surcharg g. Convertit la re eprsentation so ous forme de chane spcifie d'une date et d'une e heure en DateT Time quivale ent. Surcharg g. Soustrait l'heure ou la dure spcifie s de cette e instance. Surcharg g. Substitu. Convertit la valeur de cette instance e en sa reprsent tation sous forme e de chane quivale ente. Converti it la valeur de l'objet DateTime e en cours en Temp ps universel coor rdonn (UTC). Surcharg g. Convertit la re eprsentation so ous forme de chane spcifie d'une date et d'une e heure en DateT Time quivale ent.

S S S S

op_Addition n op_Equality y op_GreaterT Than Parse Subtract ToString ToUniversal lTime TryParse

Exemple DateTime D dt3=newDateTime(2008,10,2); DateTime D dt4=newDateTime(2008,10,4); TimeSpan T ts=TimeSpan.From mDays(2); Console.Write C Line(dt3==dt t4); Console.Write C Line(dt3>dt4 4); Console.Write C Line(DateTime.Compare(dt3,dt4)); s); dt3=dt3.Add(t d Line(DateTime.Compare(dt3,dt4)); Console.Write C dt3 d =dt3+ts; Line(DateTime.Compare(dt3,dt4)); Console.Write C

False False -1 0 1

Proprits P
Nom Date Day DayOfWeek DayOfYear Hour Kind Millisecond Minute Month Now Second Ticks T TimeOfDay T Today T UtcNow Year Y Description Obtient le composant "date" de ce O ette instance. O Obtient le jour du mois reprsent par cette instan nce. O Obtient le jour de semaine reprse ent par cette ins stance. O Obtient le jour de l'anne reprsen nt par cette inst tance. O Obtient le composant "heure" de la date reprsent te par cette inst tance. O Obtient une valeu ur qui indique si l'heure reprsent te par cette instance se base sur r l'heure locale, l'heure UTC, ou au ucune des deux. O Obtient le composant "millisecond des" de la date re eprsente par cette instance. O Obtient le composant "minutes" de d la date reprse ente par cette in nstance. O Obtient le composant "mois" de la a date reprsent e par cette insta ance. O Obtient un objet DateTime D qui a pour p valeur la dat te et l'heure actu uelles sur cet ordinateur, exprimes en temps loca al. O Obtient le composant "secondes" de la date reprs sente par cette instance. O Obtient le nombre e de graduations s reprsentant la date et l'heure de d cette instance. O Obtient l'heure de e cette instance. O Obtient la date ac ctuelle. O Obtient un objet DateTime D qui a pour p valeur la dat te et l'heure actu uelles sur cet ordinateur, exprimes en temps UTC C. O Obtient le composant "anne" de la date reprsente par cette inst tance.

Affichage et formatage des dates Les formateurs permettent de personnaliser des dates pour l'affichage ou la conversion de date. Ils sont utiliser par exemple avec les mthodes:
Console.WriteLine objets DateTime. ToString String.Format String.Parse

Formatsstandarts dpendantdelaculturecourante

Formats standarts INSENSIBLE la culture

Exemple:
DateTimedt5=newDateTime(2008,10,2,23,3,59,10); Console.WriteLine("affichageformatcourt{0:d}",dt5); stringstr_convert=string.Format("lamemeauformatlong{0:D}",dt5); Console.WriteLine(str_convert); Console.WriteLine(dt5.ToString("dddd,ledMMMMyyyy")); affichage format court 02/10/2008 Console.WriteLine(dt5.ToString("cedd/MMMHH:mm")); la meme au format long jeudi 2 octobre 2008 Console.WriteLine(dt5.ToString("HHheuresmmminutes")); jeudi, le 2 octobre 2008 Console.WriteLine(dt5.ToString("HH'heures'mm'minutes'")); ce 02/oct. 23:03 stringstr="2/11/09"; 23 11eure59 03 3inue59 DateTimedt7; 23 heures 03 minutes if(DateTime.TryParse(str,outdt7)==false) date convertie ds la culture fr-FR 02/11/2009 Console.WriteLine("echecduPArsenouvellesaisie"); dans InvariantCulture mois et jour sont invers else 11/02/2009 Console.WriteLine("dateconvertiedslaculture{0}{1:d}", System.Globalization.CultureInfo.CurrentUICulture,dt7); DateTimedt8; dt8=DateTime.Parse(str,System.Globalization.CultureInfo.InvariantCulture) Console.WriteLine("dansInvariantCulturemoisetjoursontinvers{0:d}",dt8);

REMARQUE: Des erreurs d'interprtation sont possibles lorsque les dates sont donnes par une tierce partie (exemple: fichier texte). En effet une ambiguit sur l'ordre du mois et du jour existe. C'est la raison pour laquelle il est prfrable d'exporter les dates en prcisant l'anne en premier. Des formateurs non sensibles la culture existent:
Prfrez le formateur 'o' qui convertit automatiquement en UTC DateTimedt9=newDateTime(2009,5,3,13,10,53); //J=5/M=3/A=200913h10mn53s Console.WriteLine("culturedependant{0:d}",dt9); Console.WriteLine("insensibleculture{0:o}",dt9);

Pour relire:
DateTime dt1 = DateTime.ParseExact (s, "o", null); ou DateTime dt2 = DateTime.Parse (s); // "o" utilis par dfaut

- 31 -

Les flux
Stream est la classe de base abstraite de tous les flux. Un flux est une abstraction d'une squence d'octets, telle qu'un fichier, un priphrique d'entre/sortie, un canal de communication processus interne, ou un socket TCP/IP. La classe Stream et ses classes drives donnent une vue gnrique de ces diffrents types d'entres et de sorties, isolant le programmeur des dtails spcifiques au systme d'exploitation et aux priphriques sous-jacents.

Classe de "stockage physique" Elle drive de la classe abstraite Stream est implmente les fonctionnalits de bases de lecture et criture vers le support physique cibl
Classes "adaptateur" Classe d'encodage permettant une manipulation des donnes par l'utilisateur sous une forme plus volu: Ex: octet -> string Octet-> xml Classes "Dcorateur" Classe d'encodage intermdiaire. Ex: crytage des donnes

Schma de principe d'utilisation Ecriture simple dans un fichier


using(FileStreamfs=newFileStream("test.txt",FileMode.Create)) {byte[]tab=newbyte[]{0x49,0x55,0x54};//"IUT"crit fs.Write(tab,0,tab.Length); }

Ecriture simple dans un fichier avec


using(FileStreamfs2=newFileStream("test2.gztxt",FileMode.Create)) { using(GZipStreamcompress_fs=newGZipStream(fs2,CompressionMode.Compress)) { byte[]tab2=newbyte[2048]; On constate que la taille du fichier est bien for(uinti=0;i<tab2.Length;i++)tab2[i]=0x49; infrieure 2Ko compress_fs.Write(tab2,0,tab2.Length); } }

La classe FileStream

Classe qui implmente pour les fichiers les mthodes gnrales de la classe gnrique stream (concepts hritage et interface vus plus loin) tels que : public override int Read(byte[] array,int offset,int count) ou public override void Write(byte[] array,int offset, int count)

- 32 -

Exemple
using System; using System.IO; using System.Text; namespace test { class Program { static void Main(string[] args) { string path=@"G:\Temp\"; string namefile="capteur.txt"; FileStream fs = new FileStream(path + namefile, FileMode.Create); byte[] ByteArray=new byte[20]; fs.WriteByte(0xFF); for (byte i=0;i< 20; i++) ByteArray[i]=i; // pas de prbleme de conversion car ByteArray // tableau d'octet fs.Write(ByteArray, 0, ByteArray.Length); string chaine = "je veux etre enregistre"; // Convert the string into a byte[] Encoding unicode = Encoding.Unicode; // choix codage byte[] unicodechaine = unicode.GetBytes(chaine); fs.Write(unicodechaine, 0, unicode.GetByteCount(chaine)); string chaine2 = "je veux etre enregistre en utf8"; fs.Write(Encoding.UTF8.GetBytes(chaine2), 0, Encoding.UTF8.GetByteCount(chaine2)); // conversion double vers string puis ASCII double val = 10.536; String strNumber = System.Convert.ToString(val); fs.Write(Encoding.ASCII.GetBytes(strNumber), 0,Encoding.ASCII.GetByteCount(strNumber)); fs.Close(); } } }

Commentaires: Lcriture de chanes de caractres ou de nombres ncessite des conversions diverses. Afin de soulager le concepteur de programmes des classes drives sont proposs pour traiter les fichiers textes et binaire.

La classe NetworkStream

La classe NetworkStream fournit les mthodes pour l'envoi et la rception de donnes via des sockets Stream en mode blocage. Tous les constructeurs require un objet de type socket connect. Il existe plusieurs mthodes: - Manipulation de la classe socket et des mthodes associs (mthode plus flexible mais aussi plus complexe) - Manipulation des classes TcpListener (ct serveur) et TcpClient (ct Client) et de la mthode GetStream() qui renvoye un socket connect!
COTECLIENT
TcpClientmonTcpClient=newTcpClient("127.0.0.1",10000); using(NetworkStreamns=monTcpClient.GetStream()) { stringchaine="marequete"; Encodingencode=Encoding.UTF8; byte[]buffer=encode.GetBytes(chaine); ns.Write(buffer,0,buffer.Length); Console.WriteLine("envoidelarequete"); byte[]response=newbyte[100]; Stringstring_response=String.Empty; Console.WriteLine("attenteresponse"); ns.Read(response,0,response.Length); string_response=encode.GetString(response); Console.WriteLine(string_response); Console.WriteLine("fin"); Console.ReadKey(); }

COTESERVEUR
IPAddressipAddress=IPAddress.Parse("127.0.0.1"); TcpListenerserver=newTcpListener(ipAddress,10000); server.Start(); Console.WriteLine("\nAttenteconnection..."); TcpClientclient=server.AcceptTcpClient();//bloquant using(NetworkStreamns=client.GetStream()) { Encodingencode=Encoding.UTF8; byte[]requete=newbyte[100]; ns.Read(requete,0,requete.Length); stringstrRequete=encode.GetString(requete); Console.WriteLine("messageduclient"+strRequete); byte[]reponse=encode.GetBytes("ACK"); ns.Write(reponse,0,reponse.Length); Console.WriteLine("\nFinserveur..."); Console.ReadKey()

Commentaires: Techniquement les flux de type rseaux n'ont pas de fin. La condition nombre d'octet lu gale 0 signifie simplement que le buffer de rception (au niveau systme) a t vid par les lectures prcdentes. Il n'est donc pas sur que l'intgralit du message ait t envoy (exemple d'une collision sur le rseau). - 33 -

Il est prfrable d'utiliser les classes BinaryWriter et BinaryReader qui facilitent la manipulation des donnes. De plus , en utilisant ces classes, les donnes sont prfixes par leur longueur. Les mthodes de lecture connaisent le nombre d'octets qu'elles doivent lire ( ce n'est pas le cas avec StreamReader qui est
dconseill pour les accs rseaux)

Adapteur de type Texte

Les classes (adaptateur) StreamReader et StreamWriter permettent de manipuler facilement du texte au travers de flux, et notament les fichiers textes .

Application la lecture ou criture de fichier Utilisez StreamReader pour lire des lignes d'informations partir d'un fichier texte standard. Utilisez StreamWriter pour crire des lignes d'informations partir d'un fichier texte standard. Les classes exposent en plus du constructeur StreamWriter(Stream) (voir exemple ci-dessous en lecture) un constructeur StreamWriter(String) qui ouvre en "sous main" un flux de type fichier ,permettant la manipulation directe de ce fichier. Sauf spcification contraire, le codage par dfaut de StreamReader et
StreamWriter

est UTF-8.

LECTURE

ECRITURE
Exemple Flux combin
Ecriture allg: ouverture usingSystem; directe du fichier usingSystem.IO; StreamWriter("TestFile.txt") classTest { publicstaticvoidMain() { //CreateaninstanceofStreamWritertowritetexttoafile. //TheusingstatementalsoclosestheStreamWriter. using(StreamWritersw=newStreamWriter("TestFile.txt")) { //Addsometexttothefile. sw.Write("Thisisthe"); sw.WriteLine("headerforthefile."); sw.WriteLine(""); //Arbitraryobjectscanalsobewrittentothefile. sw.Write("Thedateis:"); sw.WriteLine(DateTime.Now); }

usingSystem; usingSystem.IO; publicclassCompBuf { privateconststringFILE_NAME="MyFile.txt"; publicstaticvoidMain() { if(!File.Exists(FILE_NAME)) { Console.WriteLine("{0}doesnotexist!",FILE_NAME); return; } FileStreamfsIn=newFileStream(FILE_NAME,FileMode.Open, FileAccess.Read,FileShare.Read); //CreateaninstanceofStreamReaderthatcanread //charactersfromtheFileStream. using(StreamReadersr=newStreamReader(fsIn)) { stringinput; //Whilenotattheendofthefile,readlinesfromthefile. while(sr.Peek()>1) { input=sr.ReadLine(); Console.WriteLine(input); } } } }

- 34 -

Complment sur la manipulation des fichiers Ci aprs sont prsents quelques types livrs dans lespace de nommage System.IO pour la manipulation sur les fichiers , tels que copie, dplacement, renoomage dextension etc
Classe Directory Description Exposedesmthodesstatiquespourcrer,dplaceretnumrerviadesrpertoiresetsousrpertoires.Cetteclassenepeut pastrehrite.

DirectoryInfo Expose des mthodes d'instance pour crer, dplacer et numrer des rpertoires et sousrpertoires.Cette classe ne peut pastrehrite. File Fournit des mthodes statiques pour crer, copier, supprimer, dplacer et ouvrir des fichiers et facilite la cration d'objets FileStream. Fournit des mthodes d'instance pour crer, copier, supprimer, dplacer et ouvrir des fichiers et facilite la cration d'objets FileStream.Cetteclassenepeutpastrehrite. ExcutedesoprationssurdesinstancesdeStringquicontiennentdesinformationsrelativesau chemin d'accsd'un fichier oud'unrpertoire.Cesoprationssontexcutesdiffremmentselonlaplateforme.

FileInfo

Path

EXEMPLE 1
usingSystem; usingSystem.IO; classTest {publicstaticvoidMain() { stringpath=Path.GetTempFileName(); FileInfofi1=newFileInfo(path); if(!fi1.Exists){ //Createafiletowriteto. using(StreamWritersw=fi1.CreateText()) { sw.WriteLine("Hello"); sw.WriteLine("And"); sw.WriteLine("Welcome"); } } //Openthefiletoreadfrom. using(StreamReadersr=fi1.OpenText()) { strings=""; while((s=sr.ReadLine())!=null) { Console.WriteLine(s); }} try { stringpath2=Path.GetTempFileName(); FileInfofi2=newFileInfo(path2); //Ensurethatthetargetdoesnotexist. fi2.Delete(); //Copythefile. fi1.CopyTo(path2); Console.WriteLine("{0}wascopiedto{1}.",path,path2); //Deletethenewlycreatedfile. fi2.Delete(); Console.WriteLine("{0}wassuccessfullydeleted.",path2); } catch(Exceptione) { Console.WriteLine("Theprocessfailed:{0}",e.ToString()); } } }

EXEMPLE 2
usingSystem; usingSystem.IO; namespacestreamwriter { classProgram { publicconstushortnbelt=5; staticvoidMain(string[]args) { stringpath=@"G:\Temp\"; stringnamefile="capteur.txt"; if(!Directory.Exists(path)) Directory.CreateDirectory(path); FileInfofic=newFileInfo(path+namefile); ConsoleKeyInfokeypressed; StreamWriterfictxt=null; if(fic.Exists) { Console.WriteLine("LEfichier"+namefile+"existe.Souhaitezvousl'craser?"); keypressed=Console.ReadKey(true); if(keypressed.KeyChar=='O') fictxt=fic.CreateText(); else fictxt=fic.AppendText(); } fictxt.WriteLine("capteurno;echantillonno;valeur"); for(inti=0;i<nbelt;i++) { floatval; val=(float)Math.Sin((2*Math.PI/nbelt)*i); stringconcat="capeur1;"+i+";"+val; fictxt.WriteLine(concat); } fictxt.Close(); } }
}

- 35 -

Adapteur de type Binaire

Les classes BinaryWriter et BinaryReader permettent de manipuler les objets natifs C# au travers d'un flux. Exemple en criture

publicclassFiche { stringm_nom,m_prenom; bytem_age; publicstringNom { get{return(m_nom);} set{m_nom=value;} } publicstringPrenom { get{return(m_prenom);} set{m_prenom=value;} } publicbyteAge { get{return(m_age);} set{m_age=value;} } publicFiche(stringnom,stringprenom,byte age) {Nom=nom;Prenom=prenom;Age=age;} publicoverridestringToString() { stringstrFiche=String.Format("Nom:{0} Prenom:{1}ag(e)de{2}ans",Nom,Prenom,Age); returnstrFiche; } }

classProgram { staticvoidMain(string[]args) { Fiche[]tabFiche=newFiche[2]; tabFiche[0]=newFiche("Amel","Oscar", 20); tabFiche[1]=newFiche("Copter","Elie", 22); Console.WriteLine(tabFiche[0].ToString()); using(FileStreamfs= File.Create("datafiche.bin")) { using(BinaryWriterfs_bin=new BinaryWriter(fs)) { foreach(FicheuneficheintabFiche) { fs_bin.Write(unefiche.Nom); fs_bin.Write(unefiche.Prenom); fs_bin.Write(unefiche.Age); } } } Console.ReadKey();

Exemple de relecture du fichier


using(FileStreamfs=File.OpenRead("datafiche.bin")) { using(BinaryReaderfs_binread=newBinaryReader(fs)) { while(fs_binread.PeekChar()!=1)//litcarsuivantsansdplacer //l'indexdelecture { stringnomfiche=fs_binread.ReadString(); stringprenomfiche=fs_binread.ReadString(); byteagefiche=fs_binread.ReadByte(); Console.WriteLine(nomfiche+"/"+prenomfiche+"/"+agefiche.ToString()); Console.ReadKey(); } } }

Commentaire: PeekChar() est une faon de tester la fin de fichier lorque l'on ne connat pas la taille du fichier (ici de le nombre de fiche stocke) La relecture d"un fichier binaire implique de connatre la struture interne de stockage des donnes : ici: string/string/byte.

- 36 -

Introduction aux collections


L'espace de noms System.Collections contient des interfaces et des classes qui permettent de manipuler des collections d'objets. Plus prcisment, les donnes structures classiques que l'on utilise en informatique comme les listes chans, les piles, les files d'attente, sont reprsentes dans .Net framework par des classes directement utilisables du namespace System.Collections.
Classe Array

Elle sert de classe de base pour tous les tableaux du Common Language Runtime. Tous les tableaux que vous crez manipul sont en fait de la classe Array.
Exemple usingSystem; usingSystem.Collections.Generic; usingSystem.Text; namespaceArray_exemple1 { classProgram { staticvoidMain(string[]args) { /*******************Arraydemo ***************************/ byte[]tab=newbyte[10]; Randomrnd1=newRandom(); rnd1.NextBytes(tab); foreach(byteibyteintab)Console.Write(ibyte+""); if(((IList<byte>)tab).Contains(10))Console.WriteLine("contient lavaleur10"); elseConsole.WriteLine("necontientlavaleur10"); Array.Sort(tab); foreach(byteibyteintab)Console.Write(ibyte+""); Console.WriteLine("\nnombrepair"); byte[]tab_pair=Array.FindAll(tab,Fct_Recherche_Pair); foreach(byteibyteintab_pair)Console.Write(ibyte+""); Console.WriteLine("\nredimensionnetableau"); Array.Resize<byte>(reftab,20); foreach(byteibyteintab)Console.Write(ibyte+""); Console.ReadKey(); } privatestaticboolFct_Recherche_Pair(byteval) { if((val%2)==0) return(true); 221 147 115 135 32 133 201 104 150 94 ne else contient la valeur 10 return(false); 32 94 104 115 133 135 147 150 201 221 } nombre pair 32 94 104 150 } redimensionne tableau 32 94 104 115 133 135 147 150 201 221 0 0 0 0 } 000000

Classe gnrique List<T>

'List' capable de stocker des rfrences sur des objets de type <T>. Ce tableau de type liste est dynamique et sa taille peut varier tout moment grce aux mthodes associs la classe List. La cration d'une liste ncessite au moment de la cration la spcification du type de base des objets contenus. List est donc un conteneur gnrique ( notion developpe plus loin dans ce poly). Exemple de cration d'une liste d'entier: List<int> maListeInt=new List<int>();
usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; namespaceConteneur_exemple1 { classProgram { staticvoidMain(string[]args) { Randomrnd2=newRandom(); List<int>listTab=newList<int>(10);//capacit delaliste:10elts for(inti=0;i<10;i++)//ATTENTION:LALISTE ESTVIDE,CAPACITEdiffrentdeTAILLE //listTab[i]=100;COMPILATEURKOcarlaliste estvide listTab.Add(rnd2.Next(1000));//rajoutnbre random<1000 foreach(intvalinlistTab)Console.Write(val+" ");//parcoursdelaliste listTab[0]=100;//accesuneltEXISTANT listTab.Insert(1,101);//insertionelt101 l'index1 Console.WriteLine("\ncapacitdelaliste "+listTab.Capacity);//lacapacitat redimmensionn! listTab.RemoveAt(2);//suppressioneltl'index 3 Console.WriteLine("\nListemofidifie"); foreach(intvalinlistTab)Console.Write(val+" ");//parcoursdelaliste listTab.AddRange(newint[]{10,20,30});// rajouteunecollectiond'objet Console.WriteLine("\nListemofidifie2"); foreach(intvalinlistTab)Console.Write(val+" ");//parcoursdelaliste Console.WriteLine("\nLemaxest"+listTab.Max()); Console.WriteLine("\nLamoyenneest"+ listTab.Average()); Console.ReadKey(); } } }

- 37 -

Les dictionnaires

Un dictionnaire est une collection d'objet de type cl/ Valeur. Chaque cl, qui doit tre unique, sert rfrencer l'objet dans le dictionnaire. Les recherches peuvent se faire suivant la cl (le plus rapide) ou suivant le contenu de l'objet. Diffrentes classes implmentent ce concept de dictionnaire suivant: - Que les objets puissent tre indexable ( concept tableau) - Que La collection soit ordonne ou non - Que La classe soit gnrique ou non - Les performances souhaites

Exemple: cration et mthodes de base associs aux dictionnaires


usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; namespaceDictionnaire_Simple1 { publicclassEtudiant { publicstringNom{get;set;} publicstringPrenom{get;set;} publicUInt16Age{get;set;} publicUInt32CodeApogee{get;set;} publicEtudiant(stringnom,string prenom,UInt16age,UInt32codeApogee) {Nom=nom; Prenom=prenom;Age=age;CodeApogee=codeApogee;} publicoverridestringToString() {return(CodeApogee+":"+Nom+""+Prenom+"agede "+Age.ToString()+"ans");} } classProgram { staticvoidMain(string[]args) {//creationdictionnaire Dictionary<UInt32,Etudiant>dicLPSE= newDictionary<UInt32,Etudiant>(); //ajoutdesentrees dicLPSE.Add(100213,new Etudiant("Oscar","Amel",21,100213)); dicLPSE.Add(100214,new Etudiant("Copter","Elie",20,100214)); //accesd'unelt(affichagenecessitesurcharge deToString) Console.WriteLine(dicLPSE[100214]); //Modificationd'unelt dicLPSE[100214]=newEtudiant("Duck","Donald", 20,100214); //testdecleavectry/catch uintcodeTest=100214; try {dicLPSE.Add(codeTest,newEtudiant("Duck", "Donald",18,100214));} catch(System.ArgumentException) {Console.WriteLine("codeapogee"+codeTest+" dejautilise");} //alternativepossibleavecrecherchedecl EtudiantunEtudiant; if(!dicLPSE.TryGetValue(100214,outunEtudiant)) Console.WriteLine("Noval");//"Noval" else Console.WriteLine(unEtudiant); //Methode1:parcoursdudictionnairepourchaque couplecle/valeur Console.WriteLine(""); foreach(KeyValuePair<UInt32,Etudiant>kvin dicLPSE) Console.WriteLine(kv.Key+";"+kv.Value); //Methode2:parcoursdudictionnairepourchaque cle Console.WriteLine(""); foreach(UInt32codeindicLPSE.Keys) Console.WriteLine(code+"/"+dicLPSE[code]); //Methode2:parcoursdudictionnairepourchaque "valeur" Console.WriteLine(""); foreach(EtudiantetudindicLPSE.Values) Console.WriteLine(etud); Console.ReadKey(); } } }

Manipulation des donnes: LINQ

A partir de la version 3.0 de C#, des fonctionnalits supplmentaires sur la manipulation des donnes ont t rajouts au langage, regroupes dans l'espace de noms: Language-Integrated Query.(LINQ).
L'objectif n'est pas de prsenter les fondements de LINQ mais de montrer , par le biais d'exemple, la puissance de ces fonctions associs des conteneurs. Pour plus de complments veuillez vous reporter la bibliographie Exemple : Dictionnaire et Extraction de donnes

- 38 -

usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; namespaceDictionnaire_Compare { publicclassEtudiant { publicstringNom{get;set;} publicstringPrenom{get;set;} publicUInt16Age{get;set;} publicUInt32CodeApogee{get;set;} publicEtudiant(stringnom,stringprenom,UInt16age,UInt32codeApogee) {Nom=nom;Prenom=prenom;Age=age;CodeApogee=codeApogee;} publicoverridestringToString() {return(CodeApogee+":"+Nom+""+Prenom+"agede"+Age.ToString()+"ans");} } classProgram { staticvoidMain(string[]args) {//creationdictionnaire Dictionary<UInt32,Etudiant>dicLPSE=newDictionary<UInt32,Etudiant>(); //ajoutdesentrees dicLPSE.Add(100213,newEtudiant("Oscar","Amel",20,100213)); dicLPSE.Add(110214,newEtudiant("Copter","Elie",21,110214)); dicLPSE.Add(110216,newEtudiant("aaaa","bbb",20,110216)); dicLPSE.Add(100215,newEtudiant("aaaa","dddd",21,100215)); Console.WriteLine("Dictionnairenontri"); IEnumerable<KeyValuePair<UInt32,Etudiant>>request1= fromkeyValueindicLPSE//poureltdudictionnaire(doncuncouple<cle,valeur>) where(keyValue.Value.CodeApogee>100000)&&(keyValue.Value.CodeApogee<110000)//filtre selectkeyValue;//renvoieles<cle,valeur>correspondant foreach(varkvinrequest1)//request1estunecollectionde<cle,valeur> Console.WriteLine(kv.Value);//kv.Valueestuneetudiant,appellasurchageToString Console.WriteLine(""); varrequest2=fromkeyValueindicLPSE//vardetypeIEnumerable<KeyValuePair<UInt32,Etudiant>> where(keyValue.Value.Age==20)//filtreage=20 orderbykeyValue.Value.Nom//trieascendantduresultatdefiltrage selectkeyValue;//where(keyValue.Value.Nom).StartsWith("aa");//renvoiedesvaleurkeyValue foreach(varkvinrequest2) Console.WriteLine(kv.Value); Console.WriteLine(""); varrequest3= fromkeyValueindicLPSE //triesenchains:paragedecendant,puispasnom,puisparprenom orderbykeyValue.Value.Agedescending,keyValue.Value.Nom,keyValue.Value.Prenom selectkeyValue; foreach(varkvinrequest3) Console.WriteLine(kv.Value); Console.WriteLine(""); varrequest4= fromkeyValueindicLPSE where(keyValue.Value.Nom).StartsWith("aa")//filtreNomcommencantpar"aa" where(keyValue.Value.Age==20)//puisfiltreAge=20 selectkeyValue;//projectiondesvaleurs foreach(varkvinrequest4) Console.WriteLine(kv.Value); Console.WriteLine(""); varrequest5= fromkeyValueindicLPSE //constitiondegroupeenfonctiondes2premierchiffreducodeApogee groupkeyValueby(keyValue.Value.CodeApogee.ToString()).Substring(0,2)intogrps selectgrps;//projectiondesssgroupe foreach(varssgroupeinrequest5)//pourchaquessgroupedelarequete { Console.WriteLine("groupeayantpourcle"+ssgroupe.Key); foreach(varkvinssgroupe)//pourchaqueeltdessousgroupe Console.WriteLine(kv.Value);//afficheetudiant } Console.WriteLine(""); varrequest6= fromssgrpeinrequest5//pourchaquessgrpedelarequete5 fromkvinssgrpe//pourchaqueeltdessousgroupes wherekv.Value.Age==20//neretientqueceruxdontAge=20 selectkv;//projectiondeselts foreach(varkvinrequest6) Console.WriteLine(kv.Value); Console.ReadKey();}}}

- 39 -

TRAVAIL PERSONNEL
1- Manipulation de fichiers a. Ecrire dans un fichier 'texte' les 100 premires valeurs de la fonction y= Le format sera: valeur de x;valeur de y \n avec un encodage utf16. b. Ecrire le programme de relecture des valeurs avec un affichage l'cran c. Refaire la mme chose avec un fichier 'binaire' d. Reprendre la question 1 et rajouter un champ date/temps au fichier: Date/temps; valeur de x;valeur de y La date initiale sera saisie au clavier, puis chaque chantillon crit dans le fichier, le temps sera avanc de 1h Le format de la date sera de type o (insensible la culture voir paragraphe correspondant) 2- Ecrire un client/serveur tcp simplifi a. Tester le bon fonctionnement en local (127.0.0.1) de votre client/serveur envoyant la chane de caractre "ON\n" chaque appui sur la barre espace. Vous utiliserez les mthodes BinaryWriter/ BinaryReader sur un flux NetwokStream pour l'envoi et la rception des donnes. Vous ouvrirez 2 instances de Visual Studio, une avec le serveur que vous lancerez en premier et l'autre avec le client b. L'ordre de commande est maintenant:" ON;xx\n"; ou "OFF;yy\n avec xx et yy: valeur de 1 10. Le serveur interprtera cette commande (revoir les string et la commande Split) et horodatera la rcepttion commande sous la forme "Lundi 3 Novembre 10:23. Vous utiliserez la fonction DateTime.now.

3- Conteneur de type List<string> a. Crer une liste avec les sept couleurs de l'arc en ciel b. Afficher la liste par ordre alphabtique (Mthode Sort) c. Rajouter la couleur "rmarron" d. Afficher le nombre d'lement dans la liste (proprit Count) e. Tester si la couleur "rose" est prsente (Mthode Contains) f. En vous inspirant de l'exemple du cours et en utilisant la mthode FindAll: i. Ecrire la mthode statique permettant de trouver toutes les couleurs ayant 5 lettres ii. Ecrire la mthode statique permettant de trouver toutes les couleurs se terminant par "ge"

4- Travail de recherche: la classe WebClient Cette class permet de faire une requete sur un serveur http et de recuprer via la mthode DownloadFile le rsultat: Voci un exemple tester chez vous pour afficher utilise le serveur mto de yahoo (ATTENTION: pas de proxy dans cette exemple)
using(WebClientclientWeb=newWebClient()) clientWeb.DownloadFile("http://weather.yahooapis.com/forecastrss?w=628879&u=c", "page.html");//628879codepourtoulon System.Diagnostics.Process.Start("page.htm");

Faire une petite application graphique qui affiche la cartographie d'un lieu en se basant sur google map static: Etape 1:comprendre la requete envoyer au serveur avec un navigateur taper http://maps.google.com/maps/api/staticmap?xxxxxxxx
xxxxxhttp://code.google.com/intl/fr/apis/maps/documentation/staticmaps/

Etape 2: faire une interface graphique la plus simple: 1 bouton Update+ 1 pictureBox pour afficher le fichier png retourn par le serveur google La mise jour de l'image se fera artir du code suivant nadapter en fonction de vos besoins:
fs=newFileStream("img.png",FileMode.Open,FileAccess.Read); pictureBox1.Image=Image.FromStream(fs); fs.Close();//importantderelacherlaressource

- 40 -

TP
Conteneur de type List< DataCapteur > On se propose de crer une liste contenant la resultat de diffrents capteurs. Chaque capteur est repr par un identifiant unique.Crer la classe DataCapteur suivante La mthode ToString est surcharge afin d'afficher les informations du capteur. 1- Crer la classe et une liste contenant diffrentes valeurs ( pas de saisie clavier, utiliser directement la mthode Add). Vrifier avec un affichage de la liste. 2- Rajouter les mthodes statiques: a. FindIdEven ,utilise par la mthode FindAll de la classe List<T>, qui testera la parit de l'identifiant (voir exemple du cours). b. SortById, utilise par la mthode Sort(Comparison<T>) de la classe List<T>, qui permettra de tri des capteurs da,s l'ordre de leur identifiant. Vous utiliserez dans SortById la mthode objetxx.ToCompare(objetyy) ave Exemple:http://msdn.microsoft.com/en-us/library/w56d4y5z.aspx 3- Faire une requete LINQ pour trier par identifiant descendant puis par valeur ascendante 4- Faire une requete LINQ pour regrouper les capteurs par Id puis calculer ' la main', pour chaque capteur, la moyenne des valeurs de ce capteur.

Client POP3 simple Le projet suivant consiste, partir d'un client TCP et en tudiant le protocole POP3 (voir synoptique cidessous + http://www.commentcamarche.net/contents/internet/smtp.php3), d'envoyer les diffrentes requetes afin de rcuper les mails sur un serveur POP3 et des afficher en mode console. Les recommandations: - Vous pouvez utiliser outlook express (msimn.exe) coupl ArgoSoft. - Les mails envoys sont stocks au format .eml dans les rpertoires aux noms des utilisateurs que vous aurez cr (voir TP prcdent). Vous pouvez directement les supprimer pour faire le 'mnage' au besoin. - Le client doit rester simple. Les pices jointes ,les encodages MIME de type Base64 ne sont pas traits. Il est donc recommand de choisir le format d'encodage 'texte brut' sur outlook express. - La lecture du flux TCP se fera au niveau octet. - La convertion byte-> string peut se faire par exemple sous cette forme:
string
code=Encoding.ASCII.GetString(uneliste.ToArray());

Le cahier des charges: - Une seule contrainte: vous devrez utiliser des listes! - Vous crerez les classes que vous souhaitez: Par exemple les classes : Message: reflte le contenu d'un message. A minima: sa taille plus une liste de chaines string (info du serveur+ sujet+ body etc) POP3Simple qui contiendra par exemple une liste des Messages plus des mthodes telles que login (user,password) etc...

- 41 -

HERITAGE ET DERIVATION
Il est fortement recommend, pour une bonne assimilation du cours, de reprendre les exemples (copier/coller) et de les tester par vous-mme (et si possible en pas pas). concept
L'hritage permet de construire de nouvelles classes (classe fille) drivant d'une classe existante (classe mre).La classe drive(fille) hrite automatiquement des donnes et du savoir-faire de la classe mre. Elle peut bien sr ajouter de nouvelles donnes et de nouvelles fonctionnalits qui lui sont propres. Ce mcanisme est appel spcialisation. Un ensemble de classes obtenues par drivation successive forme une hirarchie de classe. La notion d'hritage et de drivation est rapprocher de la notion d'ensemble. Cette vision ensembliste permet de dfinir des sr-ensembles et des sous-ensembles. La classe fille est un sous-ensemble de la classe mre. Quelques exemples pour fixer les ides : Classe de base Individu Vhicule Animal Animal En prenant l'exemple de la classe animal graphiquement nous pourrions reprsenter sous forme d'ensemble : Animal

mammifres

reptiles

Que peut-on en conclure : un mammifre est un animal un animal n'est pas forcment un mammifre un reptile est un animal les animaux possdent des caractristiques communes (poids, ge .) et des fonctions communes ( manger, crier etc)

Les mammifres, en plus des caractristiques communes tous les animaux, possdent leurs propres caractristiques ainsi que des mthodes propres.

Hritage ou inclusion : L'hritage exprime donc une relation du type est un . Par exemple : un chien est un mammifre. Une voiture est un vhicule. L'inclusion, c'est--dire lorsqu'une classe rutilise pour sa dfinition une autre classe ( exemple d'une classe rectangle utilisant une classe Point), exprime une relation possde un ou un . Par exemple : Un rectangle possde des points. Une voiture un chssis.

- 42 -

Mis en uvre
En C# une classe ne peut hriter que d'une autre classe. L'htirage multiple est interdit. La syntaxe pour exprimer une drivation est la suivante : class B : A o A est apelle classe de base, "superclasse",classe mre o B est appelle classe drive, classe spcialise, classe fille. Un exemple pour fixer les ides :
usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; namespaceheritage1 { enumRACE{INCONNU,GOLDEN,CAIRN,DANDIE, SHETLAND,DOBERMAN,LAB}; publicclassMammifere { //propritsautomatique protectedintAge{get;set;} protectedintPoids{get;set;} privateintNbrePattes{get;set;} //constructeurs publicMammifere() {Console.WriteLine("CtorMammifere1");} publicMammifere(intf_age,intf_poids,int f_nbre_patte) { Console.WriteLine("CtorMammifere2"); Age=f_age;Poids=f_poids;NbrePattes=f_nbre_patte; } publicvoidCrier(){Console.WriteLine("Raaaa");} publicvoidDormir(){Console.WriteLine("Zzzzz");} publicoverridestringToString() {//NbrePattesinaccessible //j'appelebase.ToString()etjerajoutelesinfos spcifiquesduChien stringretourToStringdeLaClasseMammifere= base.ToString(); return("age"+Age+",poids"+Poids+",pattes "+NbrePattes); } } classChien:Mammifere { publicRACERace{get;set;}

publicChien(RACEf_ace,intf_age,int f_poids,intf_nbre_patte) { Race=f_ace; Age=f_age; Poids=f_poids; //this.NbrePattes=f_nbre_patteompilKOcar NbrePattesestprivate! } publicChien(intf_age,intf_poids,int f_nbre_patte):base(f_age,f_poids,f_nbre_patte) { Race=RACE.INCONNU; } publicoverridestringToString() {//NbrePattesinaccessible //j'appelebase.ToString()etjerajoutelesinfos spcifiquesduChien stringretourToStringdeLaClasseMammifere= base.ToString(); return("Chien"+ retourToStringdeLaClasseMammifere+"Race"+Race); } }; classProgram { staticvoidMain(string[]args) { MammifereunMamifere=newMammifere(10,5,2); unMamifere.Crier(); Console.WriteLine(unMamifere); ChienunChien=newChien(RACE.GOLDEN,5,10,4); Console.WriteLine(unChien); unChien.Dormir(); unChien.Crier(); ChienautreChien=newChien(2,1,4); Console.WriteLine(autreChien); Console.ReadKey(); } } }

Commentaire : la classe chien drive de la classe mammifre. Ceci implique que les fonctions membres de la classe chien peuvent accder aux champs et proprits du chien en fonction du niveau de visibilit: public : tout le monde protected : RESCTRICTIONS AUX CLASSES DERIVEES
Ctor Mammifere 2 Raaaa age 10, poids 5, pattes 2 Ctor Mammifere 1 Chien age 5, poids 10, pattes 0Race GOLDEN Zzzzz Raaaa Ctor Mammifere 2 Chien age 2, poids 1, pattes 4Race

protectedintAge privateintNbrePattes

private: RESTRICTION A LA CLASSE DE BASE

- 43 -

L'ide de base de la drivation est de pouvoir partager certaines proprits et certaines mthodes de la classe de base vers les classes drives. La classe de base est le "dnomitateur" commun d'un ensemble de classe drive: Exemple:unChien.Dormir();etunChien.Crier Cependant nous remarquons ici que l'action unChien.Crier ne produit pas une action atisfaisante. La mthode Crier doit tre "spcialise" et adapte pour reflter le cri d"un Chien: "Ouarffff"

La cration d"un objet drive, ici un chien, implique une squence d"initialisation logique: 1. Appel du ctor de chien 2. Appel du ctor de mammifre :implicite => appel de Mammifere() ou explicite => Chien(yyyyy):base(xxxxxx) 3. Excution du code du ctor de mammifre 4. Excution du code du ctor de mammifre

La spcialisation
Nous avons vu que la classe de base peut intgrer des mthodes communes toute les classe drives. Par exemple la mthode crier de la classe Mammifere peut tre vu comme une fonction gnrique commune toutes les espces. Cependant le cri d'un chat ou d'un chien n'est pas le mme videmment. Il faut donc substituer la fonction crier de base fournie par la classe mre, avec la fonction crier spcifique des classes filles Chat et Chien par exemple. Ce mcanisme est appel aussi substitutions de fonction. Un exemple :
namespaceheritage1 { enumRACE{INCONNU,GOLDEN,CAIRN,DANDIE, SHETLAND,DOBERMAN,LAB}; publicclassMammifere { //propritsautomatique protectedintAge{get;set;} //constructeurs publicMammifere(){Console.WriteLine("Ctor Mammifere1");} publicMammifere(intf_age) { Console.WriteLine("CtorMammifere2"); Age=f_age; } //methodes publicvoidCrier() {Console.WriteLine("Raaaa");} Ctor Mammifere 2 Raaaa } Ctor Mammifere 2 Ctor Chien 2 classChien:Mammifere Ouarfff {//propitauto publicRACERace{get;set;} //ctor1 publicChien(intf_age,RACE f_race):base(f_age) {Console.WriteLine("CtorChien2");Race =f_race;;} //specialisation //newestoptionnel=>evitewarning compilateur //newprcisel'intentionduconcepteurde spcialisatlamthode publicnewvoidCrier(){ Console.WriteLine("Ouarfff");} }; classspecialise { staticvoidMain(string[]args) { MammifereunMamifere=newMammifere(10); unMamifere.Crier(); ChienunChien=newChien(5,RACE.GOLDEN); unChien.Crier(); Console.ReadKey(); } } }

Convertion de type

Convertion implicite et explicite Le langage prvoit la possibilit de rfrencer : - 44 -

un objet de type classe drive partir d'une rfrence de Type classe de Base

MammifereunMammifere2=newMammifere(5); ChienunChien2=newChien(5,RACE.GOLDEN); MammifereautreMammifere2=unChien2;//Upcast

Cette convertion de type est appele "UpCast". Cette convertion russie toujours condition de respecter la filiation des classes (convertion drive vers Base ou encore classe fille vers classe mre) un objet de type classe de Base partir d'une rfrence de Type classe drive
MammifereunMammifere2=newMammifere(5); ChienunChien2=newChien(5,RACE.GOLDEN); ChienautreChien2=(Chien)unMammifere2;//Downcast

Cette convertion de type est appele "DownCasting". Cette convertion NE russie PAS toujours. Dans ce cas une exeception est leve l'xecution (runtime) car un mammifre n'est pas forcment un Chien, l'inverse par contre tant toujours vrai! Cette convertion n'est donc pas de type "safe-fail".

Oprateur is et as
Ces oprateurs sont utiliser pour des convertions de type safe-fail, c'est--dire sans leve d'exception au runtime. L'oprateur as permet de raliser une convertion de downcasting.La rfrence rsultat est positionne null en cas d'chec. L'oprateur is permet de raliser un test de conversion. Le resultat, un boolean , est utilis pour raliser effectivement la convertion en cas de succcs.
//downcastavecas MammifereunMammifere=newMammifere(5); ChienautreChien=unMammifereasChien; if(autreChien!=null) autreChien.Crier(); else Console.WriteLine("convertiondwoncastimpossible"); //upcastavecis ChienunChien=newChien(5,RACE.GOLDEN); if(unChienisRACE) ((Mammifere)unChien).Crier(); else Console.WriteLine("convertionupcastimpossible");

Mthode virtuelle
Une fonction ou une mthode est qualifie de virtuelle lorsque le mot-cl virtual est en prfixe de sa dclaration. L'objectif d'une telle dclaration virtuelle est de pouvoir appeler la mthode de substitution adquate partir d'une rfrence de base pointant vers des objets de type classe drive : ce mcaniqme est apeel polymorphisme (voir paragraphe suivant) Pour illuster le propos, reprenons l'exemple des mammifres avec 2 classes drives: Chat et Chien
usingSystem; usingSystem.Text; namespacevirtualexmple { publicclassMammifere { //methodes publicvirtualvoidCrier(){Console.WriteLine("Raaaa");} publicvirtualvoidSous_Ordre_Especes(){Console.WriteLine("Mammifere");} publicvoidNbreDePattes(){Console.WriteLine("Inconnu");} } classChien:Mammifere { publicoverridevoidCrier(){Console.WriteLine("Ouarfff");} publicvoidSous_Ordre_Especes(){Console.WriteLine("Canids");}

- 45 -

publicvoidNbreDePattes(){Console.WriteLine("Chien:4pattes");} }; classChat:Mammifere { publicoverridevoidCrier(){Console.WriteLine("Miaouu");} publicoverridevoidSous_Ordre_Especes(){Console.WriteLine("Flids");} publicvoidNbreDePattes(){Console.WriteLine("Chat:4pattes");} }; classconvert { staticvoidMain(string[]args) Miaouu rsultatdemam1.Crier();mam1bienqu'tantdetypemammifre"comprend"grceau {ChienunChat=newChat();KOimpossible couplevirtual/overridequel'objetpointeestunChat Mammiferemam1=newChat();//UpcastOK Flids rsultatdemam1.Sous_Ordre_Especes();mmeremarque mam1.Crier(); Inconnu rsultatdemam1.NbreDePattes();c'estlamthodedelaclassemammifre mam1.Sous_Ordre_Especes(); quiatappel! mam1.NbreDePattes(); mam1=newChien();//mam1pointeversunchienmaintenantUpcastOK mam1.Crier(); Ouarfff -rsultatdemam1.Crier();effetdevirtuarl/overrideenplace mam1.Sous_Ordre_Especes(); Mammifere -rsultatmam1.Sous_Ordre_Especes();overrideabsentdanslaclassedrive mam1.NbreDePattes(); rsultatdemam1.NbreDePattes();c'estlamthodedelaclassemammifrequia Inconnu Console.ReadKey();} }}

tappel! virtualABSENTsurNbreDePattes(classeMammifere) virtualABSENTsurNbreDePattes(classeMammifere)

Polymorphisme
Plusieurs objets de natures diffrentes peuvent avoir des fonctionnalits similaires mais implmente diffremment au sein de chaque objet (c'est la spacialisation). Le cas prcdent en est un exemple : tous les mammifres ont un cri mais qui diffrent finalement en fonction de chaque espce. Le polymorphisme ( qui possde plusieurs formes ), permet de donner un mme nom chacune de ses actions. La bonne action sera slectionne contextuellement en fonction de la classe d'objets laquelle elle s'applique. L'intrt de cette approche est de pouvoir unifier un traitement appliqu des objets de nature diffrente: En reprenant l'exemple prcdent des mammifres:
//Onregroupetoutlemondesousletypedebase List<Mammifere>maMenagerie=newList<Mammifere>(); //Jepeuplelamnagerie maMenagerie.Add(newChat()); Miaouu maMenagerie.Add(newChien()); Ouarfff maMenagerie.Add(newMammifere() Raaaa //Jefaiscriertouslemonde foreach(MammiferemaminmaMenagerie) TRAITEMENTDEBASEAPPLIQUEADESOBJETSDIFFERENTS(MAIS mam.Crier(); APPARTENANTALAMMECLASSEDEBASE)

Exemple dapplication polymorphique Prenons l'exemple d'une application manipulant un ensemble d'objets graphiques.Chacun de ces objets possde une mthode de calcul de surface et de primtre. La gnralisation du concept d'objets graphiques aboutit une classe ObjetGraphique contenant les fonctions virtuelles surfaces et primtres. Il est possible alors de stocker tous les objets manipuls par l'application dans un tableau du type ObjetGraphique.

- 46 -

ObjetGraph hique[]monTableau= monTableau u[0]=newRectangle(..) monTableau u[1]=newCer rcle(..) monTableau u[2]=newCer rcle(..) foreach(O ObjetGraphiqueobjinmo onTableau) obj j.CalculSurf face();

Chaque case e du tableau est une rf rence sur de es objets diff frents mais que appartie ennent la m mme famille. f Grce e la virtualis sation les m thodes de su urface et prim mtre sont polymorphiques (codes diffrents en fonction de d la nature e de l'objet): la fonction adquate a est automatique ement appel le. Le po olymorphisme e fournit un n niveau d'abst traction lev e : il est e possible de d demander r un objet gra aphique de ca alculer son p rimtre o sa surface san ns avoir beso oin de connatre c pr cisment sa classe relle. . Les avantage es : -possibilit de dfinir un n corps diffre ent pour une fonction pour r des classes diffrentes - manipula ation d'un ens semble d'obje ets de faon g gnrique san ns connatre le eur type - possibilit t d'ajouter de es classes d rives suppl mentaires sa ans retoucher r au code.

La classe e object
Il s'agit de la classe de bas se fondamentale parmi tou utes les class ses du .NET F Framework. La plupart des s classes c que vous v manipule ez hritent de e object . Cette C classe constitue c la ra acine de la hi rarchie des types. t

public class Ob bject { public Object(); T GetType() ); public extern Type public virtual bool Equals (obj ject obj); public static bo ool Equals (obje ect objA, objec ct objB); o public static bo ool ReferenceE Equals (object objA, o object o objB); nt GetHashCod de(); public virtual in public virtual st tring ToString() ); protected override void Finali ize(); protected exter rn object Memb berwiseClone(); }

Com mmme toutes les classes du .NET Framework sont driv ves de Object, toutes les mthodes d finies dans la a class se Object son nt disponibles s dans la totalit des objets s du syst me. Les clas sses drives s peuvent sub bstituer certain nes de ce es mthodes, notamment : Equals - Prend P en cha arge les comp paraisons entr re objets. Finalize - Effectue des s oprations de d nettoyage automatiquem ment rcupr . avant qu'un objet soit a GetHashC Code - Gnr re un nombre e corresponda ant la valeur de l'objet pou ur prendre en charge l'utilisation d'une table de hachage. ToString - Fabrique un ne chane de texte explicite e qui e instance de la classe. dcrit une

Complments s: ToString T : Pa ar dfaut la m thode ToString applique e une de vos propres classes renverra a le type sous s forme f de cha ane de caract tre. Vous comprenez mai intenant mieu ux la syntaxe utilise depui is le debut po our personnaliser r laffichage de d vos classes s:
publicoverridestringToString()//spcialisationdelaclass se ToString()ici i appelleToStringde elaclassemre { //base.T //+"Aut teur:"+Aute eur;etona ajoutelesinfos i spcif fiqueslaclassefille Auteur; stringchaine=base.ToString()+"Auteur:"+A return(chaine); }

GetHashCode : certains conteneurs ( Dictonnary, SortedList ..) utilise une cl dite de hachage, en fait tout simplement un entier, pour indexer les lments du conteneur. Tous les lments ayant une mme cl sous regroup dans un mme de panier (bucket). La cl de hachage, qui nest pas unique mais suffisant distincte ne doit pas tre confondu avec la cl didentification dun dictionnaire, qui elle est unique et qui permet de retrouver llment dans un panier. Hash code : identifiant panier Possible davoir 2 paniers indexs 691 !!!

Couple <Key,Data> : Key :cl unique didentification de la valeur Data : valeur que lon souhaite stock

Comment construire le hash code . Afin doptimiser les algorithmes de recherches et dindexation, votre mthode GetHashCode doit renvoyer un entier suffisament unique . Il ny pas de rgles absolues mais lexamen de vos classes permet de vous donner des pistes. Exemples divers pour vous aider :
publicoverrideintGetHashCode() { return_unChampInt.GetHashCode(); } ---------------------------------------------------------publicoverrideintGetHashCode(Customerobj) { return(obj.prenom+";"+obj.nom).GetHashCode(); } ---------------------------------------------------------public override int GetHashCode() { return coordx ^ coordy; // OU exclusif ---------------------------------------------------------public override int GetHashCode () { return a.GetHashCode() ^ b.GetHashCode() ^ c.GetHashCode(); ---------------------------------------------------------publicoverrideintGetHashCode() { returnMeasure2*31+Measure1;//31=unnombre premier } ----------------------------------------------------------

- 48 -

Classe abstraite
Une classe est dite abstraite lorsque le prfixe abstract est rajout devant le mot cl class :
abstractclassA_Fiche { Protectedintvaleur=10; publicvoidtest(){Console.WriteLine("test");} publicintAccessValeur{get;set;} }

Une classe abstraite ne peut tre instantie directement :


vartest=newA_Fiche1();//KO SOLUTION classFiche1:A_Fiche { } varref_Fiche=newFiche1(); ref_FichehritedeA_Fiche(etdeObject aussi)

Une classe abstraite permet de dclarer des membres abstrait (sans corps de fontion). Les classes drives hritant de la classe abstraite SONT OBLIGES dimplmenter le corps de la mthode.
abstractclassA_Fiche { protectedintvaleur=10; publicvoidtest() {Console.WriteLine("test");} abstractpublicintAccessValeur {get;set;}//PASDECORPS!!!! } classFiche1:A_Fiche1 { //OBLIGATIONdIMPLENTERlACCESSEUR! publicoverrideintAccessValeur { get{return(valeur);} set{valeur=value;} } }

REMARQUE:lefaitdedclarerunemthodeabstraiteouvredroitaupolymorphisme (quivalentcrirevirtual).ToutelesfichepeuventtremanipulecommedesA_Fiche

Limite de l'hritage
Introduction

Les notions de drivation et d'hritage permettent de construire plus aisment de nouvelles classes en s'inspirant d'un modle de base (la classe que l'on drive). Ainsi, plutt que de partir de rien, la nouvelle classe drive hrite d'un certain nombre de fonctionnalits. L'objectif est donc de structurer le programme et de factoriser le code en exploitant la relation "EST un" :un chien EST UN mammifre. Cependant l'hritage n'est pas la panace et certaines limtes existent. Critique de l'exemple prcdent Comment traiter alors une Baleine qui est un mammifre aussi mais qui n'a pas de patte? Nous souhaitons traiter la capacit des mammifres voler? Faut t'il mettre voler dans la classe de base? Voici un exemple de modifications apports l'exemple:

- 49 -

publicclassMammifere { //methodes publicvirtualvoidCrier(){Console.WriteLine("Raaaa");} publicvirtualvoidSous_Ordre_Especes(){Console.WriteLine("Mammifere");} publicvirtualvoidNbreDePattes(){Console.WriteLine("Inconnu");} } classBaleine:Mammifere { publicoverridevoidNbreDePattes(){Console.WriteLine("jen'aipasdepatte");} publicoverridevoidCrier(){Console.WriteLine("Mouuuuu");} publicoverridevoidSous_Ordre_Especes(){Console.WriteLine("Ctacs");} } classChauveSouris:Mammifere { publicoverridevoidNbreDePattes(){Console.WriteLine("jen'aipasdepatte");} publicoverridevoidCrier(){Console.WriteLine("Mriiiiii");} publicoverridevoidSous_Ordre_Especes(){Console.WriteLine("chiroptres");} publicvoidVole(){Console.WriteLine("Flapflap");} } classconvert { staticvoidMain(string[]args) { ChauveSourisuneChauveSouris=newChauveSouris(); uneChauveSouris.Vole();//OKcaruneChauveSourisdutypeuneChauveSouris //Onregroupetoutlemondesousletypedebase List<Mammifere>maMenagerie=newList<Mammifere>(); //Jepeuplelamnagerie maMenagerie.Add(newChauveSouris()); //maMenagerie[0].Vole();KOmaMenagerie[0]faitrfrenceunmammifere //Vole()n'estpasdanslaclassedebase! maMenagerie.Add(newBaleine()); //Quivoledaansmamnagerie???? foreach(MammiferemaminmaMenagerie) //mam.Volant();KO:volantn'estpasdanslaclassedebase!

Remarques: Nous constatons que la spcialisation rajoute la chauve-souris ne permet pas d'appliquer un traitement de base du type: qui vole? (polymorphisme). Une solution consiste intgrer Vole() dans mammifre en virtual. Ceci nous amnera surchager toutes les classes drives. Le code produit n'est donc pas robuste et une modification du cahier des charges implique une retouche de toutes les classes. La question est alors de savoir comment injecter des comportements des objets non lis spcifiquement la classe de base ( un animal volant n'est pas une spcifit des mammifres). Les "interfaces" en C# rpondent en autre cette question. Les interfaces dfinissent un certain de nombre de fonctionnalit que les classes choissisent ou non d'implanter. Cette notion d'interface sera dtaille plus loin dans ce chapitre Voici l'exemple recrit avec des interfaces:

- 50 -

//FonctionVole interfaceIVolant {voidVole();} //Fonctionadespattes interfaceIPatte {//dfinitiond'unepropritenlecture intNbPatte{get;} } //classedebase publicclassMammifere { //methodescommunestouslesmammifres publicvirtualvoidCrier(){Console.WriteLine("Raaaa");} publicvirtualvoidSous_Ordre_Especes(){Console.WriteLine("Mammifere");} } //Chienestunmammifrequiaaussidespattes classChien:Mammifere,IPatte {//ImplantationdeNbPattedfinidansIPatte publicintNbPatte {get{return(2);} } //surchargepolymorphedesclassesdebases publicoverridevoidCrier(){Console.WriteLine("Ouarfff");} publicoverridevoidSous_Ordre_Especes(){Console.WriteLine("Canids");} } classBaleine:Mammifere {//surchargepolymorphedesclassesdebases publicoverridevoidCrier(){Console.WriteLine("Mouuuuu");} publicoverridevoidSous_Ordre_Especes(){Console.WriteLine("Ctacs");} } //Chienestunmammifreaveclesfonctionnalits:pattes+volant classChauveSouris:Mammifere,IVolant,IPatte {//ImplantationdeNbPattedfinidansIPatte publicintNbPatte {get{return(2);} } //ImplantationdeVoledfinidansIVolant publicvoidVole(){Console.WriteLine("Flapflap");} //surchargepolymorphedesclassesdebases publicoverridevoidCrier(){Console.WriteLine("Mriiiiii");} publicoverridevoidSous_Ordre_Especes(){Console.WriteLine("chiroptres");} } classconvert { staticvoidMain(string[]args) { ChauveSourisuneChauveSouris=newChauveSouris(); uneChauveSouris.Vole(); //Onregroupetoutlemondesousletypedebase List<Mammifere>maMenagerie=newList<Mammifere>(); //Jepeuplelamnagerie maMenagerie.Add(newChauveSouris()); maMenagerie.Add(newBaleine()); maMenagerie.Add(newChauveSouris()); maMenagerie.Add(newChien()); //Quivoledansmamnagerie???? foreach(MammiferemaminmaMenagerie) { if(mamisIVolant) ((IVolant)mam).Vole(); else Console.WriteLine("NonVolant"); } //Alleztouslemondecrie foreach(MammiferemaminmaMenagerie) mam.Crier();//triatementdebasecrier=>polymorphisme

- 51 -

Alternative l'hritage

Cette partie n'est pas aborde dans notre cours car elle implique une bonne matrise des notions d'intertaces, d'hritage. Des indications sont donnes pour ceux qui devront dans leur profession appronfondir les connaissances prsents ici et mettre en uvre des techniques professionnelles de programmation. Voici quelques extraits et liens vers des informations sur ces sujets

PatrickSmacchia (article "assez pointu") http://www.dotnetguru.org/articles/dossiers/heritageimpl/FragileBaseClass.htm


"Les deux techniques alternatives lhritage dimplmentation pour rutiliser du code dans un programme crit dans un langage orient objet sont : La composition dobjets : un objet (lobjet encapsulant ou outer object en anglais) en encapsule un autre (lobjet encapsul ou inner object en anglais). Lobjet encapsulant ne doit jamais communiquer lextrieur une rfrence vers lobjet encapsul. Une consquence est que lobjet encapsulant est responsable du cycle de vie de lobjet encapsul. Une autre consquence est que diffrents objets encapsulant, ventuellement instances de classes diffrentes, peuvent utiliser une mme implmentation pour leurs objets encapsuls. A linverse, une mme implmentation dobjets encapsulant peut utiliser diffrentes implmentations dobjets encapsuls. Il y a donc bien ici possibilit de rutiliser du code, soit du cot de limplmentation de lobjet encapsul, soit du cot de limplmentation de lobjet encapsulant. Les interfaces : Lorsque les interfaces sont utilises conjointement avec la composition dobjets, on peut alors rutiliser du code tout en bnficiant du polymorphisme que lon avait avec lhritage dimplmentation (i.e, on ne connat pas exactement limplmentation que lon utilise, on sait juste quelle respecte un certain contrat, matrialis par linterface en loccurrence). En outre si une interface est suffisamment explicite, il nest pas ncessaire daller analyser le code de ses implmentations pour lutiliser correctement. Ce phnomne est connu sous le nom de black-box reuse, en opposition au terme white-box reuse dj cit. "

Site du zero :Les limites de l'hritage : le pattern strategy


Article trs clair montrant l'implantation de fonctionnalit variant dans le temps l'aide de la composition d'objet couple aux interfaces

Les designs patterns


Un livre de rfrence : Design Patterns: Elements of Reusable Object-Oriented Software crit par ceux surnomms "The Gang of Four(Gof)" (utilisez les mots cls Gof et designs patterns) Indispensable pour une programmation "professionnelle".

- 52 -

Les interfaces
Concept

La notion d'interface rejoint en partie la notion de de classe abstraite. Une classe abstraite est une classe marqu abstract qui dfini une ensemble de fonctionnalits (mthodes) sans corps associ. Une classe concrte est une classe pour laquelle l'ensemble des fonctionnalits jusqu'alors abstraites ont toutes t concrtises. Une fonctionnalit concrte est une fonction membre qui possde un corps (c'est dire du code). Une interface peut tre vue donc comme un modle de classe qui contient les prototypes des mthodes et des proprits (attributs qui servent accder d'autres). Chaque classe qui choisira d'implmenter l'interface devra respecter le contrat impos et fournir une implmentation de l'interface (ie fournir le code des mthodes) . Exemple
interfaceIVolant {voidVole();} //Fonctionadespattes interfaceIPatte {//dfinitiond'unepropriten lecture intNbPatte{get;} } classChauveSouris:Mammifere,IVolant,IPatte {//ImplantationdeNbPattedfinidansIPatte publicintNbPatte {get{return(2);} } //ImplantationdeVoledfinidansIVolant publicvoidVole(){Console.WriteLine("Flapflap");}

Remarques: par convention le nom donn aux interfaces est prfix par un I : IVolant,IPatte,Ixxxxx les interfaces n'ont pas de constructeurs les interfaces ne dfinissent pas de code des mthodes (concept abstraction) les interfaces n'ont pas de champs Les mthodes sont toutes publiques par dfaut
Intrt des interfaces

Les interfaces , lors de l'tude d'un projet, permettent de dfinir en amont les fonctionnalits attendues des objets sans pour autant figer ou imposer de solutions techniques. Une fois dfinies, elles obligent toutes les classes clientes de ces interfaces respecter le contrat : dans un travail en quipe par exemple l'architecte logiciel ayant dfini les interfaces , les objets et leurs interactions les programmeurs devront respecter les choix imposs (conventions, mthodes, fonctionnalits .) L'hritage multiple tant interdit (choix des concepteurs du C#), les interfaces permettent de dcrire des fonctionnalits, non spcifique la classe de base ,attendues des objets. Exemple Tous les mammifres ne sont pas volants: fonction spcifique des chauve-souris (interfaces Ivolant) Les ouvrages (livres, DVD) d'une bibliothque ne sont pas tous empruntables (interfaces IEmpruntable qui contiendra sans doute un historique des emprunts). Par contre tous les ouvrages ont un genre, possde un identifiant unique, une date de cration etc (=> invariant dans le temps=> classe de base) Des formes en 2D ont toutes la facult de renvoyer un primtre, une surface (=> classe de base). Certaines formes sont dfinies l'aide d'une liste de point (rectangle , carr, losange, triangle), d'autre non ( cercle) => interface Ipoint

Le polymorphisme dinterface

Les interfaces permettent au polymorphisme d'oprer de manire trs simple en manipulant les objets au travers d'une rfrence de type interface.

- 53 -

Exemple 1:
List<Ivolant2>maMenagerieVolante=newList< Ivolant2>(); //Jepeuplelamnagerie maMenagerie.Add(newChauveSouris()); maMenagerie.Add(newCanari()); maMenagerie.Add(newPerroquet()); maMenagerie.Add(newpterodactyle()); foreach(Ivolant2animalVolantin maMenagerieVolante) animalVolant.VitesseDePointe();

On constate qu'il est possible de regrouper des objets n'appartenant pas la mme classe de base!! ( Canari n'est pas un mammifre). Il suffit juste que la classe de touts ces objets implmente Ivolant2.

Remarque : il faut bien comprendre List<Ivolant2>maMenagerieVolantemaintient une liste de rfrnce vers des objets en mmoires. Ces objets , lors de leur cration , ne sont pas tronqu en mmoire. maMenagerie.Add(newChauveSouris()); ralise 2 oprations : - Cration dun objet complet en mmoire de type Chauve-souris Stockage dans liste dune rfrnce vers cet objet en tant queIvolant2 Tant que cette chauve souris est manipule en tant que Ivolant2seule les proprits et mthodes des Ivolant2 seront accesibles. A tout moment il est possible de changer de point de vue par une opration de cast pour accder pleinement lobjet : (ChauveSouris)maRfrenceIvolant2 condition bien entendu que maRfrenceIvolant2 rfrence linstant t une chauve-souris !!!

Exemple 2:
List<Mammifere>maMenagerie=newList<Mammifere>(); //Jepeuplelamnagerie maMenagerie.Add(newChauveSouris()); maMenagerie.Add(newBaleine()); maMenagerie.Add(newChauveSouris()); maMenagerie.Add(newChien()); //Quivoledansmamnagerie???? foreach(MammiferemaminmaMenagerie) { if(mamisIVolant) ((IVolant)mam).Vole(); else Console.WriteLine("NonVolant"); } //Alleztouslemondecrie foreach(MammiferemaminmaMenagerie) mam.Crier();//triatementdebasecrier=>polymorphisme

On constate qu'il est possible de regrouper des objets n'implmentant pas tous l'interface Ivolant, et de retrouver puis d'effectuer un traitement commun tous les volants (!en utilisant les cast!)

Interface Explicite et Rsolution de conflit


Il est possible de rsoudre les conflits de noms en explicitant, lors de l'implantation de la mthode, le nom de l'interface. interfaceI1{voidFoo();} interfaceI2{intFoo();} publicclassWidget:I1,I2 { Widgetw=newWidget(); publicvoidFoo() w.Foo();//Widget'simplementationofI1.Foo {Console.WriteLine("Widget'simplementationofI1.Foo");} ((I1)w).Foo();//Widget'simplementationofI1.Foo intI2.Foo() ((I2)w).Foo();//Widget'simplementationofI2.Foo { Console.WriteLine("Widget'simplementationofI2.Foo"); return42; } }

- 54 -

Interface IEquatable et IEqualityComparer

Le framework .NET fournit un nombre important d'intreface rpondant des problmes classqiues de l'algorithmique: - Comment cloner des objets ICloneable<T> - Comment parcourir une liste : IEnumerable<T> - Comment tester l'galit des objets: IEquatable<T> et IEqualityComparer<T> Comment comparer des objets: IComparable<T> et IComparer<T> IEquatable<T> Le comportement par dfaut d'un test d'galit x==y ou x.Equals(y) est: - Pour les types valeurs: vrai si les donnes sont indentiques - Pour les types valeurs: vrai si les rfrences sont indentiques! ( et non pas le contenu des objets) L'interface IEquatable dfinit la mthode Equals, qui dtermine l'galit des instances du type d'implmentation. Exemple:
publicclassTemperature:IEquatable<Temperature> { //ImplmentationdeIEquatable //paramtre<T>detypeTemperature publicboolEquals(Temperatureother) {//appeldemthodepardfautEqualsdestypesparvaleursdouble.Equals returnm_Temperature_Moyenne.Equals(other.m_Temperature_Moyenne); } //CHAMPS protecteddoublem_Temperature_Moyenne=0.0; //ACCESSEURS publicdoubleKelvin { get {returnm_Temperature_Moyenne;} set { if(value<0.0) thrownewArgumentException("Temperature>0svp"); else m_Temperature_Moyenne=value; } } //CTOR publicTemperature(doubledegreesKelvin1,doubledegreesKelvin2) { this.Kelvin=(degreesKelvin1+degreesKelvin2)/2; } } publicclassExample { publicstaticvoidMain() temprature moyenne { temprature moyenne List<Temperature>temps= temprature moyenne newList<Temperature>(); temps.Add(newTemperature(2017.15,1000)); temps.Add(newTemperature(0,100)); temps.Add(newTemperature(50,50)); foreach(Temperaturetintemps) if(t.Equals(temps[1])) Console.WriteLine("tempraturemoyennegale"); else Console.WriteLine("tempraturemoyennediffrente"); Console.ReadKey(); } } public interface IEquatable<T> { bool Equals (T other); }

diffrente gale gale

- 55 -

IEqualityComparer<T> Cette interface est utilise par certains d'algorithmes travaillant avec les conteneurs et en particulier les requtes LINQ.Alord que IEquatable peut-tre vu comme le comportement par dfaut de l'galit d'un certain type d'objet, IEqualityComparer permet de mettre en place plusieurs scnarios diffrents d'galit au travers par exemple de requte LINQ. IEqualityComparer prvoit l'implmentation de la comparaison d'galit personnalise pour le type T: boolEquals(Tx,Ty). Vous noterez au passage la diffrence avec le prototype bool Equals (T other) public interface IEqualityComparer<T> { bool Equals (T x, T y); int GetHashCode (T obj); } Exemple: Soit la mthode d'extensions de la classe Stack publicstaticIEnumerable<TSource>Distinct<TSource>( thisIEnumerable<TSource>source, IEqualityComparer<TSource>comparer ) Lecture du prototype IEnumerable<TSource>:qui renvoie une reference vers un type IEnumerable (autrement dit une collection "parcourable" avec un foreach Distinct<TSource>:MthodeDistinct ayant <pour parametre un objet T>

thisIEnumerable<TSource>source : this indique la syntaxe spcifique aux mthodes d'extensions.La source sur laquelle porte notre requete doit implmenter l'interface IEnumerableC'est le cas ici puique nous travaillons avec une pile publicclassStack<T>:IEnumerable<T>,ICollection,IEnumerable

IEqualityComparer<TSource>comparer:reference vers un objet implmentant IEqualityComparer donc par la mme la mthode bool Equals (T x, T y)

- 56 -

;
publicclassTemperatureComparerClass: IEqualityComparer<Temperature> {//ScnariodiffrentdeIEquatable:Tempraturegalesi T1.1=T2.1etT1.2=T2.2 publicboolEquals(Temperaturetemp1,Temperaturetemp2) { if((temp1.Temperature_Capteur1== temp2.Temperature_Capteur1)&& (temp1.Temperature_Capteur2== temp2.Temperature_Capteur2)) returntrue; elsereturnfalse; } publicintGetHashCode(Temperaturetemp) {//utilisparDictionnaryouSortedListpourdfinirunecl INTERNEderangement //pasd'obligationd'treunique(maissuffisammentdiffrente) //HashCode<>deKey!!!Keydoittreuniquecarclde recherchedevosdonnes return((int)(temp.Temperature_Capteur1* temp.Temperature_Capteur2)); }} publicclassTemperature:IEquatable<Temperature> { //ImplmentationdeIEquatable //paramtre<T>detypeTemperature publicboolEquals(Temperatureother) {//appeldemthodepardfautEqualsdestypesparvaleurs double.Equals return Temperature_Moyenne.Equals(other.Temperature_Moyenne); } //propritsAUTO publicdoubleTemperature_Moyenne{get;set;} publicdoubleTemperature_Capteur1{get;set;} publicdoubleTemperature_Capteur2{get;set;} //CTOR publicTemperature(doubledegreesKelvin1,double degreesKelvin2) { Temperature_Capteur1=degreesKelvin1; this.Temperature_Capteur2=degreesKelvin2; Temperature_Moyenne=(degreesKelvin1+degreesKelvin2)/ 2; } }

publicclassExample { publicstaticvoidMain() { Stack<Temperature>temps= newStack<Temperature>(); temps.Push(newTemperature(2017,1000));temps.Push(newTemperature(0,100));temps.Push(newTemperature(2017,1000)); temps.Push(newTemperature(50,75));temps.Push(newTemperature(100,0)); foreach(Temperaturetintemps) { Console.Write("Compare{0}{1}avecref{2}{3}", t.Temperature_Capteur1,t.Temperature_Capteur2, temps.Peek().Temperature_Capteur1,temps.Peek().Temperature_Capteur2); if(t.Equals(temps.Peek()))//Peekrenvoiel'objetaudessusdelapile Console.WriteLine("tempraturemoyennegale"); else Console.WriteLine("tempraturemoyennediffrente"); } //Miseenplaced'unscnariodiffrentpourlesrequetesLINQ IEnumerable<Temperature>tempSansDoublons=Enumerable.Distinct(temps,newTemperatureComparerClass()); varrequete2=tempSansDoublons.Where(temp=>((temp.Temperature_Capteur1>50)&& (temp.Temperature_Capteur1>25) )); foreach(Temperaturetinrequete2) Console.WriteLine("tempraturecapt1:{0}capt2:{1}",t.Temperature_Capteur1,t.Temperature_Capteur2); Console.ReadKey();}

- 57 -

TRAVAIL PERSONNEL
Ex : Copier le programme ci-dessous. Excutez le en mode pas pas ,indiquez pour chaque ligne la valeur prise par le champ valeur et commentez en consquence ce programme. Remplacer le mot cl override dans Fiche2 par new. Que se passe til ?
abstractclassA_Fiche { protectedintvaleur=10; publicvoidtest(){Console.WriteLine("test");} abstractpublicintAccessValeur{get;set;} } classFiche1:A_Fiche { publicoverrideintAccessValeur { get{return(valeur);} set{valeur=value;} } } classFiche2:Fiche1 { publicoverrideintAccessValeur { get{return(valeur);} set{valeur=2*value;} } } classabstrait1 { staticvoidMain(string[]args) { Fiche1ref_Fiche=newFiche1(); A_Fiche1ref_A_Fiche1=ref_Fiche; ref_A_Fiche1.AccessValeur=20; Fiche2ref_Fiche2=newFiche2(); ref_Fiche=ref_Fiche2; ref_Fiche.AccessValeur=2; ref_A_Fiche1=ref_Fiche2; ref_A_Fiche1.AccessValeur=60; }}

Ex1 : crer une classe pointcol, driv de PointSimple, comme suit :

Les mthodes de la classe de base ne sont pas virtuelles. Affiche est spcialise (surchage) dans la classe drive PointCol. Vous utiliserez le mot cl base pour faire appel des mthodes de la classe de base (constructeur de PointCol et Affiche) Tester vos classes en crant un point ,un point couleur et en appelant les mthodes. Faire une opration de downcast : PointSimpleunPtcast=unPtCol; et tester Console.WriteLine(unPtcast.Affiche()); Que ce passe til ?

- 58 -

Crer un tableau de PointSimple o seront stocks des PointSimple mais aussi des PointCol. Balayer le tableau et appliquer tous les objets la mthode Affiche. Apporter les modifications ncessaires votre programme pour que laffichage garde son sens en fonction de lobjet en cours. Comment sappelle le mcanisme que vous avez misen uvre ?

Ex2 Cet exercice sera rcomplter en TP dans le cadre de ltude du design patern dcorateur. Codez le diagramme suivant : Le ctor de Clio et Scenic initialise les champs _libelle avec le nom de la voiture (clio ou scenic) et le champ _prix avec un prix de vente que vous choissirez. La mthode UsineClio effectue un simple affichage Biilancourt-France par exemple. La mthode ToString ralise un affichae du prix de vente et du libell de la voiture.

Crez une clio et testez les mthodes. Crez une liste de IFicheProduit : ajouter 2 scenic et 1 Clio Balayer la liste et afficher tous les voitures de la liste. Rajouter en suite laffichage de lendroit de fabrication des Clio ( utilisez les oprateurs as ou is).

- 59 -

TP
Ex1 : Soit la hierrachie des classes suiavntes

La mthode VIRTUELLE ValeurAmortissement() d'Ouvrage permet de calculer la valeur d'un ouvrage en fonction de son age selon la formule (1-x%)d avec d= jour coul entre date actuelle- date d'achat et x: pourcent de dprciasation de l'ouvrage chaque jour (par exemple 0,1%): Vous pourrez utiliser: Math.Pow,TimeSpanpour la diffrenceet la propritxx.Daysqui renvoie jes hours

La mthode ToString de la classe de base, surchage, renvoie une chaine avec la date d'achat . Les mthodes ToString des classes drives complte m'information avec leurs champs spcifiques en rutilise ToString de Ouvrage (stringchaine=base.ToString()+"Ralisateur:"..)

Faire un programme qui permette de crer une liste douvrage. Peupler cette liste. Balayer la liste ainsi cre et : Afficher louvrage en cours :Console.WriteLine(ouvrage);//appeldeToString Calculer la valeur de louvrage Mettre jour la valeur globale du stock

Afficher la valeur totale de votre stock.

- 60 -

TP :Etude du design pattern decorateur Veuillez lire les documentations fournies en TP sur ce pattern. Lexercice 2 de la prparation est repris. On souhaite traiter le problme des options rajoutes aux vhicules :par exemple climatisation, peinture mtallise, intrieur en bois etc. En ne tenant compte que des 3 options cites nous aboutissons 9 combinaison possibles ! La solution consistant driver de la classe clio toutes les possiblits (clioavecclim drive clio) nest pas viable car elle entrane une explosion combinatoire des classes. Le design pattern Dcorator porpose une solution bas sur le schma UML suivant : Classe abstraite(ou interface) IFicheProduit
Oprations de bases : Accesseurs Prix et Libell Affichage Classes mre dcorateur (utile si nombreux dcorateurs)

Classes Clio , Scenic etc

OptionClimatisation Rajoute le comportement

ClimPuissance

Les points cls : *MISE EN PLACE DES CLASSES : - COMPONENT : classe abstraite dfinissant les comportements communs aux objets : mthode(s ) Opration(s) - CONCRETECOMPONENT : concrtisation des classes : voiture du type CLIO, SCENIC - DECORATOR : Cette classe encapsule (symbole UML de COMPOSITION) une rfrence vers un objet de type COMPONENT : Component component avec component le nom de la rfrnce vers le type Component Dlgue les mthodes Opration vers la classe mre :component.Operation() => exploitation du polymorphisme (voir flches en pointilles) CONCRETE DECORATOR : Dlgue les mthodes Opration vers les classes de bases (voir flches en pointilles) Rajoute des champs spcifiques (addedStated) Rajoute des comportements spcifiques (AddedBehavior) * MANIPULATION DES CLASSES : Exemple de crtaion dobjet :
IFicheProduituneVoitureClio=newClio(); OptionBoisInterieurclioInterieurBois=newOptionBoisInterieur(uneVoitureClio,EssenceBoisDisponible[1]); OptionClimatisationclioAvecClimetBoisInterieur=newOptionClimatisation(clioInterieurBois);

On notera le chainage ainsi obtenu.

- 61 -

Travail raliser Complter lexercice 2 de la prparation avec les classes suivantes :


Rfrence vers la classe de Base => composition dobjet

Le ctor initialise la rfrence _vehiculeDecorerfrence

Oprations : accs aux champs libll et prix

Optionnel :Renvoie la rfrnce _vehiculeDecorerfrence

Constante initialiser directement dans la classe ex= 300Watt

Exemple dappel du ctor : newOptionBoisInterieur(uneVoitureClio,chene); faire dans le ctor : mettre jour le prix de la voiture en fonction de loption _vehiculeDecore.PrixDeVente=_vehiculeDecore.PrixDeVente+3000; _vehiculeDecore.DescriptionMateriel+="+Optioninterieurbois"; Equivalent dans le schma UML: component.Opration(). Ici , au travers de la rfrence de lobjet, on accde via les accesseurs (PrixDeVente etDescriptionMateriel)auchampsprixetlibell.

Cette mthode est statique. Elle permet de retourner sous forme de tableau de string les essences de bois disponibles . En effet le type enum EssenceBois sera dclarer private, le rendant inaccecible depuis lextrieur ! Vous utiliserez : Pour convertir un string en type enum. essenceChoisie=(EssenceBois)Enum.Parse(typeof(EssenceBois),p_essenceBois); Pour convertir un type enum en tableau de chaine Enum.GetNames(typeof(EssenceBois))

Vous commencerez par OptionClimatisation Vous crerez une clio. Afficher le prix et le libell. Dcorer cette clio dune clim.Affichez le prix et le libell. Affichez la puiisance de la climatisation. Effectuer en pas pas le programme et reprsenter sur papier les diffrents objets manipuls. Complter avec OptionBoisInterieur. Crer une scenic avec clim+BoisIntrieur par exemple. Tester les convertions de type :

- 62 -

Vous aimerez peut-être aussi