Automne 2018
Le Langage C#
Support de cours
Fayçal Abouzaid
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 2
Sommaire
1. Présentation du .NET Framework........................................................................................... 6
1.1 Objectifs............................................................................................................................. 7
1.2 Vue générale de l’architecture .NET ............................................................................... 7
1.3 Les Langages .NET.......................................................................................................... 8
1.4 Common Language Runtime........................................................................................... 8
1.5 Les différents types d’applications................................................................................... 9
1.6 Assemblages....................................................................................................................... 9
1.7 Environnement de développement ................................................................................ 10
1.8 Premier projet C# : Quelques concepts......................................................................... 11
1.9 Les interfaces graphiques ............................................................................................... 12
2. Éléments de base du langage C#........................................................................................... 14
2.1 Historique du langage C# .............................................................................................. 14
2.2 Conventions pour l’écriture des programmes................................................................ 14
2.3 Les types en C# ............................................................................................................... 15
2.4 Les opérateurs.................................................................................................................. 19
2.5 Les caractères et les chaînes de caractères.................................................................... 20
2.6 LesTypes nullables.......................................................................................................... 23
2.7 Les énumérations : Enum............................................................................................... 23
2.8 Les expressions régulières : La Classe regex.............................................................. 24
3 Les structures de décision et de répétition............................................................................ 28
3.1 Les opérateurs.................................................................................................................. 28
3.2 Les instructions de décisions.......................................................................................... 29
3.3 Les instructions de répétitions ....................................................................................... 31
3.4 Les tableaux..................................................................................................................... 33
4 Classes et objets....................................................................................................................... 37
4.1 Introduction..................................................................................................................... 37
4.2 Classes.............................................................................................................................. 37
4.3 Les structures : Struct...................................................................................................... 49
4.4 Visual Studio et les classes.............................................................................................. 51
4.5 Classes .NET d’usage courant ....................................................................................... 52
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 3
5 Les fonctions membres........................................................................................................... 54
5.1 Définition des fonctions membres................................................................................. 54
5.2 Méthodes virtuelles et redéfinies.................................................................................... 54
5.3 Classes et méthodes abstraites ....................................................................................... 57
5.4 Surcharge de méthodes................................................................................................... 58
5.5 Passage de Paramètres.................................................................................................... 59
5.6 Propriétés sous la forme d’expressions.......................................................................... 61
5.7 Les indexeurs................................................................................................................... 61
5.8 La surcharge des opérateurs........................................................................................... 63
5.9 Les attributs ..................................................................................................................... 64
6 Les Exceptions ........................................................................................................................ 66
6.1 Erreurs et exceptions....................................................................................................... 66
6.2 Lancer une Exception..................................................................................................... 66
6.3 Exemples d’exceptions : ................................................................................................. 66
6.4 Capturer une Exception.................................................................................................. 67
6.5 Organisation des gestionnaires ...................................................................................... 68
6.6 Instruction try-finally ............................................................................................ 68
6.7 Instruction try-catch-finally.............................................................................. 68
6.8 Exceptions personnalisées.............................................................................................. 69
6.9 Relancer une exception................................................................................................... 70
6.10 Utilisation de StackTrace........................................................................................... 70
6.11 Opérateur de condition null : ?. (C#6)........................................................................ 71
6.12 Filtres d’Exceptions (C#6) ............................................................................................. 71
6.13 Nameof (C#6)............................................................................................................... 72
7 Délégués et Événements......................................................................................................... 73
7.1 Définition d'un délégué .................................................................................................. 73
7.2 Déclaration des délégués ................................................................................................ 73
7.3 Création du délégué ........................................................................................................ 74
7.4 Invocation du délégué..................................................................................................... 74
7.5 Associer un délégué à plusieurs méthodes.................................................................... 75
7.6 Ajouter ou supprimer des délégués................................................................................ 76
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 4
7.7 Utiliser les méthodes .NET............................................................................................ 78
7.8 Les événements ............................................................................................................... 78
8 Les Interfaces........................................................................................................................... 81
8.1 Déclaration de l’interface................................................................................................ 81
8.2 Membres........................................................................................................................... 81
8.3 Implémentation de l’interface ........................................................................................ 82
8.4 Utiliser is pour tester les types...................................................................................... 83
8.5 Utiliser as pour convertir................................................................................................. 84
8.6 Cacher les membres d’une classe de base..................................................................... 84
9 L’interface Graphique (WinForms)........................................................................................ 87
9.1 Contrôles .......................................................................................................................... 87
9.2 Boutons ............................................................................................................................ 89
9.3 Les étiquettes (Label)...................................................................................................... 89
9.4 Boîte de texte ................................................................................................................... 90
9.5 Les contrôles RadioButton et CheckBox....................................................................... 91
9.6 Le contrôle RichTextBox................................................................................................ 92
9.7 Les contrôles ListBox et CheckedListBox .................................................................... 94
9.8 Menus............................................................................................................................... 95
10 Introduction à Windows Presentation Foundation........................................................... 96
10.1 Introduction..................................................................................................................... 96
10.2 Principales caractéristiques de WPF.............................................................................. 96
10.3 Créer une application WPF simple ................................................................................ 97
10.4 Contrôle TextBox............................................................................................................ 99
10.5 Contrôle Bouton Radio............................................................................................... 100
10.6 Ajouter supprimer dynamiquement un élément ......................................................... 101
10.7 Créer un Menu............................................................................................................... 101
11 Collections et itérateurs - Génériques.............................................................................. 104
11.1 Exemples de collections................................................................................................ 104
11.2 La classe non générique ArrayList............................................................................... 104
11.3 Utilisation des énumérateurs........................................................................................ 106
11.4 Itérateurs ........................................................................................................................ 108
11.5 Les collections génériques............................................................................................ 109
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 5
12 ADO.NET.......................................................................................................................... 115
12.1. SQL Server et Visual Studio.......................................................................................... 115
12.2. Les Bases de ADO.NET............................................................................................... 117
Références .......................................................................................................................................... 128
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 6
1. Présentation du .NET Framework
“The .NET Framework is an integral Windows component for building and running the next
generation of software applications and Web services.”
Le Framework .NET est un ensemble d’outils de programmation proposés par Microsoft qui
permettent au programmeur de développer différents types d’applications : des applications
console, Windows Form ou WPF, des services Web, des applications Windows mobile et bien
d’autres.
La dernière mouture en date du Framework .NET est la version 4.7. Les différentes dates de
sorties des différentes versions présentées dans le tableau ci-dessous. Chaque mise à jour apporte
son lot de nouveautés et d’améliorations.
Version Date Visual Studio Distribué avec
1.0 Février 2002 Visual Studio
Windows XP Tablet and Media
Center Editions
1.1 24 Avril 2003 Visual Studio 2003 Windows Server 2003
2.0 7 Novembre 2005 Visual Studio 2005 Windows Server 2003 R2
3.0 6 Novembre 2006 Windows Vista, Windows Server 2008
3.5 19 Novembre 2007 Visual Studio 2008 Windows 7, Windows Server 2008 R2
4.0 12 Avril 2010 Visual Studio 2010
4.5 15 Aout 2012 Visual Studio 2012 Windows 8, Windows Server 2012
4.5.1 17 Octobre 2013 Visual Studio 2013
4.5.2 5 Mai 2014
4.6 20 Juillet 2015 Visual Studio 2015 Windows 10, Windows Server 2016
4.7 5 Avril 2017 Visual Studio 2017 Windows 10 Creators Update
4.7.1 Octobre 2017
4.7.2 Avril 2018
Core SDK 2.1.5
(Source Wikipedia)
Visual Studio Community est désormais gratuit. Il peut être téléchargé à l’adresse :
https://www.visualstudio.com/fr-fr/downloads
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 7
1.1 Objectifs
Les objectifs du .NET Framework sont nombreux. On peut citer :
• Une approche unifiée pour la conception d’applications : Win, Web, services, …
• Des facilités pour le développement et le déploiement d’applications,
• Une grande facilité d’intégration et interopérabilité entre différents composants.
Le Framework est constitué de deux composants:
• Le Common Language Runtime (CLR) qui est l’environnement d’exécution des
applications .NET
• Une librairie de classes unifiée partagée par les différents langages, la .NET Class
Library.
1.2 Vue générale de l’architecture .NET
La Common Language Specification (CLS) est une spécification qui gère la compatibilité des
langages avec le Framework, ce qui permet d’utiliser n’importe quel langage compatible, qui sera
ensuite compilé par son compilateur associé qui produira un programme en code intermédiaire
(Common Intermediate Language - CIL) anciennement MicroSoft Intermediate Language
(MSIL).
Le programme CIL sera ensuite traduit par la Common Language Runtime (CLR) en code natif
sur n’importe que plateforme où elle sera installée. La CLR traduit le CIL selon les besoins
spécifiques de l’application et de la machine hôte, c’est ce qui s’appelle la compilation ‘Just in
Time’ (JIT) et qui optimise donc les performances.
Ce fonctionnement largement inspiré de celui de la machine virtuelle JAVA, facilite la migration
d’un langage de développement spécifique vers la plateforme .Net (exemple du Visual Basic vers
le VB.Net).
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 8
L’architecture générale de la plateforme .NET est représentée par le schéma suivant :
1.3 Les Langages .NET
Tous les langages .NET sont nés égaux :
• Pas de différences fonctionnelles car plusieurs fonctionnalités ont été déplacées du
langage au framework comme par exemple les accès aux fichiers.
• Les différences sont surtout au niveau syntaxique et au niveau de certaines
caractéristiques bien précises.
• Il n’y a pas de différences de performances pour le code managé, c-à-d, exécuté par le
CLR.
• Tous les langages sont compilés en CIL et exécutés par la CLR.
• Il y a un grand niveau d’interopérabilité (cross-languages) ce qui fait que l’on peut dériver
en VB.NET une classe écrite en C#, par exemple.
1.4 Common Language Runtime
“The common language runtime is the execution engine for .NET applications”
Le CLR fournit un certain nombre de services, notamment :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 9
• Le chargement et l’exécution du code,
• La compilation Juste-à-temps (JIT) qui réalise la conversion du code IL en code natif,
• La vérification de type (Common Type System),
• La gestion des exceptions,
• La gestion de la mémoire via le ‘garbage collector’ (ramasse-miettes),
• L’enregistrement dynamique des composants,
• Les contrôles de sécurité.
1.5 Les différents types d’applications
Les différents types d’applications que l’on peut développer dans l’environnement .NET sont :
• Les interfaces utilisateurs Windows (Windows Forms ou Windows Presentation
Foundation (WPF) qui est une spécification graphique plus récente de Microsoft .NET),
• Les applications en mode console Windows,
• Les services Windows,
• Les services Web, Windows Communication Foundation (WCF),
• Les applications Web, en particulier grâce à ASP.NET.
1.6 Assemblages
.NET regroupe les composants en assemblages (assemblies). Ce sont des fichiers avec l’extension
.dll ou .exe qui contiennent les classes compilées. La notion d’assemblage remplace les notions
classiques de dll et exe. Le compilateur ne génère plus de code machine mais génère un
assemblage.
L’assemblage est constitué de deux parties :
• Le langage intermédiaire (Intermediate Language - IL) qui est le code (DLL), et
• Le Metadata qui contient le manifeste décrivant le contenu de l’assemblage : nom,
version, signature, liste des fichiers, dépendances avec d’autres assemblages, infos de
sécurité, …
Chaque fichier a un nom et une clé cryptée permettant de l'authentifier.
1.6.1 Avantages des assemblages
L’utilisation des assemblages présente de nombreux avantages dont :
• L’enfer des DLLs résolu par une gestion plus restrictive des versions,
• La CLI traite les types de même noms comme distincts s’ils viennent de 2 assemblages
différents (multi-langages),
• La base des registres n’est plus sollicitée (les applications sont auto-descriptives),
• Les assemblages sont infalsifiables,
• Les assemblages sont prévus pour être portables,
• Un assemblage peut être morcelé en plusieurs fichiers.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 10
1.6.2 Structure d’un assemblage
1.7 Environnement de développement
1.7.1 Présentation
Microsoft Visual studio 2013 est un environnement puissant de développement dédié au.NET
Framework. Cependant son utilisation n’est pas obligatoire puisque les programmes C# peuvent
être compilés en ligne de commande par un compilateur C#.
Assemblage
Foo2.netmodule
Métadonnées
de type
Code IL des
méthodes des types
Ressources
(image, sons …)
Foo1.exe Image.jpg
Manifeste
Ref ver Foo2
Ref ver Image.jpg
méthodes des types
Code IL des
méthodes des types
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 11
1.7.2 Les types de projets et les templates
À la création d’un nouveau projet, Visual Studio propose de choisir entre différents langages de
programmation et différents types d’applications.
1.8 Premier projet C# : Quelques concepts
Structure
générale
− solution
− projet
− classe (!)
− point d’entrée
− namespaces
Clause « using »
Commentaires :
//, /* */
Doc Comments:
/// output:
html/xml
Références
AssemblyInfo
Sensible à la
casse
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 12
.NET permet de créer une solution pouvant contenir plusieurs projets indépendants ou reliés par
l’intermédiaire des références. Chaque projet se compose d’au moins une classe - il en contient en
fait plusieurs. Pour chaque projet, on définit un point d’entrée (méthode Main()).
Un projet peut faire partie d’un espace de nom (namespace) qui permet de mieux organiser le
code. La directive « using» au début du programme, permet d’indiquer les bibliothèques qui
sont nécessaires au projet, ce qui évite d’écrire à chaque fois le chemin complet des objets
externes que nous utilisons. Ainsi on écrira «Console.WriteLine » au lieu de
«System.Console.WriteLine».
1.9 Les interfaces graphiques
- Win Forms : C’est l’interface graphique de .NET qui fournit l’accès via la CLR à l’API
Windows. On peut donc créer grâce aux WinForms des applications graphiques intégrants
des fenêtres et plusieurs types de boutons réagissant à des évènements tels que les clics de
souris.
- Windows Presentation Foundation (WPF) est une spécification graphique introduite
depuis le Framework 3.0. Il intègre le langage descriptif XAML. Il est entièrement vectoriel,
pour le dessin comme pour le texte. Cela permet d'augmenter la taille des objets en fonction
de la résolution de l'écran sans effet de pixelisation.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 13
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 14
2. Éléments de base du langage C#
2.1 Historique du langage C#
• Version 1 : début 2001
• Version 2.0 : Visual studio 2005 ;
o Ajout des génériques, des itérateurs et des méthodes anonymes;
• Version 3.0 : Visual studio 2008
o Méthodes d’extension, les expressions lambda, LINQ (langage de requêtes);
• Version 4.0 : Visual studio 2010
o Bibliothèque parallèles de tâches (pour processeurs multi-cœurs), meilleure
prise en charge des services Web (modèle REST ou SOAP) et des WCF
(Windows Communications Foundation).
• Version 5.0 (Juin 2013) : Visual studio 2012.
o Méthodes asynchrones;
o Attributs améliorés.
• Version 6.0 (Avril 2015) : Visual studio 2015.
o Filtres d’exceptions;
o Auto-initialisation des propriétés;
o Catch et finally asynchrones;
o Constructeurs primaires …
• Version 7.1 (Août 2017) : Visual studio 2017.
o Main asynchrone avec de nouvelles syntaxes pour Main();
o Expressions Littérales par défaut ;
o Tuples ;
o Pattern matching générique ;
2.2 Conventions pour l’écriture des programmes
• Les noms des classes, structs, et méthodes commencent par une lettre majuscule
(exemple, Class1et Methode1). Si le nom est constitué de mots joints, on met en
majuscules le début de chaque mot (par exemple: MaPremiereClasse,
CalculeTonSolde).
• Commencer les noms des interfaces avec la lettre “I” (par exemple: IMonInterface
et IInterface1).
• Les noms des variables locales commencent par une minuscule et la première lettre de
chaque mot suivant est en majuscules (exemple: maVariable, tonInt, ou
monDoubleTypeVariable).
• Il conseillé d’utiliser des noms de variables significatifs qui indiquent la signification de
ce qu’ils représentent : monNumeroCompte ou tonNAS.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 15
• L’accolade ouvrante ({) doit être sur une nouvelle ligne sous la déclaration de classe ou de
membre. L’accolade fermante (}) est placée sur la même colonne sur une ligne distincte.
• Il faut laisser une ligne vide après chaque opération distincte : déclarations de variables,
boucles ou tests.
2.3 Les types en C#
Un programme C# est une collection de types :
Classes, interfaces, structures, délégués ou énumérations.
C# fournit un ensemble de types prédéfinis : int, byte, char, string, object,… Mais
on peut aussi définir ses propres types.
Les types sont des données membres d’une classe :
Champs, constantes, tableaux ou évènements
Ce sont aussi des fonctions membres d’une classe :
Méthodes, opérateurs, constructeurs, propriétés et indexeurs
Ce peut être encore d’autres types.
Il y a 2 catégories de types: les types valeur et les types référence.
2.3.1 Types valeurs et références
Le Type Valeur contient des données et ne peut avoir la valeur ‘null’. Il est constitué de :
- Primitives int i ; float x;
- Enumérations enum State { Off, On }
- Structures struct Point {int x, y;}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 16
Le Type référence : contient des références vers des objets et peut être ‘null’. Il est constitué
de :
- Racine object
- Chaîne string
- Classes class Foo: Bar, IFoo {… }
- Interfaces interface IFoo: IBar {… }
- Tableau string[] a = new string [10]
- Delegates delegate void Empty();
Remarquez que le type string est un cas particulier. C’est un type référence qui se comporte
comme un type valeur.
•••• Les types valeur
Les caractéristiques principales des types valeur sont:
• Pas d’allocation dans le tas (heap en anglais) mais sur la pile (stack) ce qui
implique une durée de vie limitée par la portée et moins de travail pour le GC,
• Une meilleure utilisation de la mémoire,
• Moins de références indirectes,
• La copie physique lors de l’assignation et du passage des paramètres (sauf ref).
Exemple
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 17
•••• Les types Référence
Les types référence héritent de System.Object. Ils sont introduits par les mots-clés :
Class, array, delegate, interface, string
La variable est une référence vers un objet alloué sur le tas; notez qu’on peut avoir plusieurs
références vers un même objet. Les objets sont créés avec le mot-clé new et détruits
automatiquement par le GC (Garbage Collector).
Il n’y a pas de copie physique lors du passage de paramètres contrairement au type valeur. Il y a
cependant une exception : le type string qui est un type référence qui se comporte comme un
type valeur.
2.3.2 Boxing et Unboxing
Les types valeurs ne sont pas alloués sur le tas. Comment peuvent-ils être utilisés dans des
structures de données ou des méthodes qui attendent une référence? Pour cela, on aura recours à
une conversion du type valeur vers une type référence (objet). Cette conversion est le « Boxing
».
L’opération inverse, c’est-à-dire convertir un objet en type valeur, s’appelle « unboxing ». Elle
est plus délicate et doit donc être explicitée, par l’utilisation d’un cast (conversion explicite).
2.3.3 Les types définis par l’utilisateur
On peut définir ses propres types de variables qui seront alors pris dans la liste suivante :
Énumérations enum
Tableaux (Arrays) int[][], string[]
Interface interface
Type référence class
Type valeur struct
Pointeur de fonction delegate
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 18
2.3.4 Les types prédéfinis
.NET offre un certain nombre de types prédéfinis
Le type entier
Les autres types numériques
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 19
2.3.5 Exemples de types
2.4 Les opérateurs
Les opérateurs permettent d’effectuer des opérations arithmétiques sur les variables.
- Opérateurs Arithmétiques : +, –, *, /
- Opérateur Modulo : %
- Opérateurs incrémentation et décrémentation : ++, ––
2.4.1 Les opérateurs d’affectation
Exemple
2.4.2 Les opérateurs de comparaison
Ils permettent de tester des conditions et renvoient une valeur booléenne (true ou false).
<, >, <=, >=, ==, !=
Avec la signification habituelle.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 20
2.4.3 La conversion entre types
Il y a 2 types de conversions : implicite et explicite selon que l’on précise ou non que l’on veut
faire une conversion. Voici 2 exemples de conversion implicite licite :
double maVar = 4 ;
float maVar = 33 ;
Les conversions implicites suivantes sont interdites :
int x = 4 ;
short z1 = x ; // erreur de compilation
double y = 3.3 ;
short z2 = y ; // erreur de compilation
Il ne doit donc pas y avoir de conversion implicite vers un type plus petit.
Pour une conversion explicite il faut utiliser un cast comme dans les exemples suivants :
short z1 = (short)x ;
short z2 = (short)y ;
2.5 Les caractères et les chaînes de caractères
2.5.1 Le type caractère : char
Les caractères sont stockés comme des caractères Unicode sur 16 bits. Exemples :
char monChar = 'A';
char monChar = 'x0041';
On peut faire un cast sur le code ASCII comme dans :
char monChar = (char)65;
2.5.2 Le Type chaîne de caractères : string
La déclaration et l’initialisation du type string sont comme suit:
string monString = "Bienvenue dans le monde du string!";
La concaténation se fait avec les opérateurs : +, +=
string salut= "Salut";
string virgule= ", ";
string monde = "Le monde!";
string monString = salut + virgule + monde;
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 21
2.5.3 La classe StringBuilder
Le type string est immutable, ce qui oblige à utiliser la classe StringBuilder pour changer le
contenu d’un string :
StringBuilder monString = new StringBuilder("Salut,");
Append
monString.Append("World!");
Insert
monString.Insert(6," "); //insérer un espace en 6ème
// position
2.5.4 Diverses opérations sur les strings
• Opérateur Egalité : ==
Console.WriteLine(tonString == monString);
• Pour accéder à un caractère de la chaîne on utilise []
Console.WriteLine(monString[7]);
• Le caractère @ évite d’utiliser l’échappement :
Au lieu de :
string monDoc = "C:DocumentsLettersfriends.doc";
On aura :
string monDoc = @"C:DocumentsLettersfriends.doc";
2.5.5 Exemple de lecture à partir du clavier
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 22
2.5.6 Convertir les Strings en Nombres
long monLong = Convert.ToInt64(monString); //convertir à long
float monFloat = Convert.ToSingle(monString);//float
double monDouble = Convert.ToDouble(monString);//double
decimal monDecimal = Convert.ToDecimal(monString);//decimal
On peut aussi utiliser Parse
Single.Parse(monString) // float
Decimal.Parse(monString) // decimal
Double.Parse(monString) // double
2.5.7 Interpolation de chaînes (C# 6)
Ce mécanisme permet d’insérer des variables dans des strings.
string person = "Paul";
Console.WriteLine($"Bienvenue, {person}!");
On peut ainsi formater la chaîne :
Console.WriteLine($"dépôt de {montant:C} dans le compte.n");
2.5.8 Formatage des résultats
On peut afficher les nombres sous différents formats qui sont :
Currency : Format monétaire
Console.WriteLine ("{0:C}", 1.2); // 1.2$
Console.WriteLine ("{0:C}", -1.2); // (1.2$)
Décimal
Console.WriteLine ("{0:D5}", 123); // 00123
Point fixe
Console.WriteLine("{0:F2}", 12);
// 12.00 – 2 chiffres après la virgule
Console.WriteLine("{0:F0}", 12);
// 12 – pas de chiffre après la virgule
Numérique
Console.WriteLine("{0:N}", 1230000000);
// 1,230,000,000.00
Scientifique
Console.WriteLine("{0:E}", 12300000); // 1.230000E+007
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 23
Héxadecimal
Console.WriteLine ("{0:X}", 123); // 7B
Console.WriteLine ("{0:X}", 65535); // FFFF
2.6 LesTypes nullables
Ils ont été introduits depuis C#2005. Ils servent à assigner la valeur null à une variable ce qui
est utile pour les Bases de Données où l’on veut pouvoir représenter un champ vide.
Déclaration:
monType? maVariable;
Exemples:
int? monInt = null;
bool? monBool = null;
float? monFloat = 1.23F;
On peut assigner une valeur par défaut à un type en utilisant l’opérateur ??
double? monDouble = null;
double monDouble1 = monDouble ?? -1.0;
2.7 Les énumérations : Enum
Les énumérations servent à grouper certaines constantes de même catégorie. Elles dérivent de la
classe System.Enum.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 24
2.8 Les expressions régulières : La Classe regex
Les expressions régulières permettent de tester le format d'une chaîne de caractères. On peut par
exemple vérifier qu'une chaîne représente une date au format "jj/mm/aa" ou qu’une adresse
courriel est valide. Pour réaliser la comparaison, on utilise un modèle (motif) et on compare la
chaîne de caractère à ce modèle.
Les expressions régulières utilisent l’espace de noms :
System.Text.RegularExpressions; qui fournit les méthodes:
• IsMatch(String) : cette méthode indique si la chaîne d'entrée est conforme à
l'expression régulière.
• Match(String) : cette méthode permet de rechercher dans la chaîne d'entrée
spécifiée la première occurrence de l'expression régulière.
• Replace(String, String): Cette méthode permet de remplace Dans la chaîne
d'entrée spécifiée, toutes les chaînes qui correspondent à un modèle d'expression
régulière par une chaîne de remplacement spécifique.
Les symboles utilisables dans un modèle sont les quantificateurs et les caractères spéciaux dont
nous présentons les plus importants ci-après :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 25
2.5.1 Les Quantificateurs
Symbole Résumé
*
Correspond à 0 ou plusieurs occurrences de l’expression qui précède. Exemple : 'zo*'
correspond à "z" et "zoo".
+
Correspond à 1 ou plusieurs occurrences de l’expression qui précède.
Exemple : 'zo+' correspond à "zo" et "zoo", mais pas à "z".
?
Correspond à 0 ou 1 occurrence de l’expression qui précède.
Exemple : 'zo(os)?' correspond à "zo" dans "zo" ou "zoos".
{n}
Correspond exactement à n fois le caractère. Par exemple, "o{2}" ne correspond pas
à "o" dans "Bob," mais aux deux premiers "o" dans "fooooot".
{n,}
Correspond à au moins n fois le caractère. Par exemple, "o{2,}" ne correspond pas à
"o" dans " Bob", mais à tous les "o" dans "fooooot".
"o{1,}" équivaut à "o+" et "o{0,}" équivaut à "o*".
{n,m}
Correspond à au moins n et à au plus m fois le caractère. Par exemple, "o{1,3}"
correspond aux trois premiers "o" dans "foooooot" et "o{0,1}" équivaut à "o?".
x|y
Correspond soit à x soit à y. Par exemple, "z|foot" correspond à "z" ou à "foot".
"(z|f)oo" correspond à "zoo" ou à "foo".
Les caractères spéciaux
Symbole Résumé
b
Délimiteur : correspond à une limite représentant un mot, autrement dit, à la
position entre un mot et un espace.
Par exemple, "erb" correspond à "er" dans "lever", mais pas à "er" dans
"verbe".
t Tabulation.
w Caractères (a-z, A-z, 0-9 et underscore).
W
Tout caractère qui n’est pas une lettre. Équivaut à "[^A-Za-z0-9_]".
^entre les crochets signifie non.
s
Correspond à tout espace blanc, y compris l'espace, la tabulation, le saut de
page, etc. Équivaut à "[ fnrtv]".
S Correspond à tout caractère d'espace non blanc. Équivaut à "[^ fnrtv]".
d Chiffres (0-9).
D Tout caractère qui n’est pas un chiffre.
. Correspond à tout caractère unique, sauf le caractère de nouvelle ligne.
$ Correspond à la fin de la saisie (chaîne ou ligne).
^ Correspond au début de la saisie
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 26
2.5.2 Les Groupes
Construction Signification
() Définit un groupe simple.
(?<name>) Groupe de nom "name"
(?i:) Ignore la casse
n
Correspond au groupe précédent (groupe #n)
Par exemple, (w)1 trouve les caractères doubles dans un mot.
k<name> Correspond au groupe précédent spécifié par son nom (name).
2.5.3 Exemples d’utilisation des ER
Voici quelques exemples d’utilisation des expressions régulières.
Exemple 1 : expression régulière pour trouver des mots dupliqués
string input;
string pattern = @"b(w+)s1b";
input = Console.ReadLine();
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
MatchCollection matches = rgx.Matches(input);
if (matches.Count > 0)
{
Console.WriteLine("{0} ({1} matches):", input,
matches.Count);
foreach (Match match in matches)
Console.WriteLine(" " + match.Value);
}
Exemple 2 : Adresse email valide
Regex valideMail = new
Regex(@"^[a-zA-Z0-9_.-]{4,30}@{1}[a-zA-Zd.-]{3,63}.{1}[a-zA-Z]{2,4}$");
Console.Write("Votre courriel : ");
string monCourriel = Console.ReadLine();
if (valideMail.IsMatch(monCourriel))
Console.WriteLine("adresse correcte!");
else
Console.WriteLine("adresse incorrecte!");
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 27
Exemple 3 : Suppression des espaces inutiles
// Suppression des espaces inutiles
string input = " Ce texte contient des espaces ";
string pattern = "s+";
string remplacement = " ";
Regex rgx = new Regex(pattern);
string resultat = rgx.Replace(input, remplacement);
Console.WriteLine("Chaîne d'origine: {0}", input);
Console.WriteLine("chaîne transformée: {0}", resultat);
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 28
3 Les structures de décision et de répétition
3.1 Les opérateurs
Les différentes catégories d’opérateurs sont :
- Les opérateurs de relation :
>, >=, <, <=, ==(égal), !=(différent)
- Les opérateurs logiques :
&&, &, ||, | , !
Exemples :
Si x=5, y=10
(x > 5) && (y == 10) // false
- Le second opérande n’est pas évalué
(x > 5) & (y ==10) // false
(x == 5) || (y == 12) // true
- Le second opérande n’est pas évalué
(x == 5) | (y ==12) // true
! (x == 7) // true
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 29
3.2 Les instructions de décisions
3.2.1 Les tests
Le test d’une condition se fait par l’instruction if dont la syntaxe est la suivante :
if (condition)
instruction(s)_1 // Si condition vraie
[else
instruction(s)_2] // Si condition fausse
Ce qui est entre [ ] étant facultatif.
Exemple
3.2.2 L’instruction switch
L’instruction switch permet de traiter plusieurs cas en une seule instruction. Sa syntaxe est la
suivante :
switch (expression) {
case constante-1:
instruction(s)
instruction de saut
case constante-2:
instruction(s)
instruction de saut
case constant-3:
...
...
[default:
instruction(s)
instruction de saut ]
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 30
Exemple
Exécution en cascade du switch : tant que l’instruction switch n’a pas rencontré un
break, l’exécution se poursuit en séquence.
switch(n)
{
case 1: // descend jusqu’au cas 3
case 2: // descend jusqu’au cas 3
case 3:
Console.WriteLine("case1 & 2 arrivent ici!");
break;
// ...
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 31
3.2.3 Expression conditionnelle
Une expression conditionnelle se fait grâce à l’opérateur ternaire ( ? : ) dont la syntaxe est :
condition ? expression_siVrai : expression_siFaux
Exemple:
resultat = (x != 0.0) ? Math.Tan(x) : 1.0;
Identique à :
if (x != 0.0)
resultat = Math.Tan(x);
else
resultat = 1.0;
3.3 Les instructions de répétitions
Les instructions de répétitions se font par l’intermédiaire de boucles qui sont au nombre de 3 :
for, while et do while.
3.3.1 Boucle for
La boucle « for » correspond à la structure « Pour » en algorithmique. Sa syntaxe est la suivante :
for ([initialisation]; [contrôle]; [incrémentation])
instruction(s)
Exemple :
for (int compteur = 1; compteur <= 5; compteur ++)
{
Console.WriteLine(compteur);
}
• continue et break
Ces 2 instructions permettent de réaliser des ruptures de séquences dans les boucles.
for (int compteur = 1; compteur <= 10; compteur +=2)
if (compteur == 3) continue;
 Permet de sauter directement à l’étape compteur = 4.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 32
for (int compteur = 1; compteur <= 10; compteur +=2)
if (compteur == 7) break;
 Sort de la boucle quand compteur == 7
Comme le montrent ces exemples, ils correspondent à des « goto » cachés et de ce fait, doivent
être évités au possible.
3.3.2 Boucle while
La boucle while correspond à l’instruction ‘Tant que’ en algorithmique. Sa syntaxe est :
while (expression)
instruction(s);
L’instruction peut ne pas s’exécuter si l’expression est fausse.
Exemple:
int compteur = 1;
while (compteur != 0)
{
compteur ++;
if (compteur == 2) continue; // Saute la valeur 2
if (compteur > 5) break; // Termine la boucle
console.WriteLine(compteur );
}
3.3.3 Boucle do-while
La boucle « do while » traduit une instruction du type « répéter jusqu’à » et sa syntaxe est donnée par :
do
instruction (s)
while (expression);
Exemple :
int x = 0;
do
{
x++;
if (x%2 != 0) // si le nombre est impair
continue;
if (x == 8)
break; // termine la boucle
console.WriteLine(x);
}
while(x < 100);
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 33
3.4 Les tableaux
Les tableaux permettent de stocker en mémoire des données du même type. En C#, un tableau
(array) est un type référence qui contient une séquence de variables d’un type donné (classe
System.Array)
Exemples de tableaux :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 34
Tableaux multi-dimensionnels
Tableau multidimensionnel rectangle
int[,] matrice = new int [3,8]
Accès aux éléments :
matrice[0,0] = 133;
Tableau multidimensionnel en escalier
int[][] tbl = new int[8][];
tbl[0] = new int[3];
tbl[1] = new int[4];
tbl[2] = new int[2];
tbl[3] = new int[4];
Accès aux éléments :
tbl[1][3] = 43;
Remarques sur les tableaux :
Le contrôle des bornes se fait par le runtime, et en cas de dépassement l’exception
IndexOfOutRangeException est levée.
Il existe d’autres structures de données qui permettent une modification dynamique du nombre
d’éléments. Voir la classe System.Collections qui contient les structures prédéfinies
ArrayList, HashTable, …
3.4.1 Utilisation des Propriétés et Méthodes avec les tableaux
Comme toute classe prédéfinie, la classe Array possède des propriétés et des méthodes prêtes à
être utilisées et dont nous présentons quelques-unes :
• La propriété Length donne le nombre d’éléments d’un tableau
int[,] monArray= new int[10,4];
Console.WriteLine(monArray.Length); // Affiche 40
• La propriété Rank donne le nombre de dimensions d’un tableau
int[,] monArray= new int[1, 3]; // 2 dimensions
int[,,] tonArray= new int[10, 4, 5]; // 3 dimensions
Console.WriteLine(monArray.Rank); // 2
Console.WriteLine(tonArray.Rank); // 3
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 35
3.4.2 Utilisation des tableaux
• La méthode Array.Sort permet de trier un tableau
int[] monArray = { 3, 4, 56, 8 };
Array.Sort(monArray); // 3,4,8,56
• La méthode Array.Reverse permet d’inverser un tableau
int[] monArray = { 3, 4, 8, 56 };
Array.Reverse(monArray); // 56,8,4,3
• Pour redimensionner un tableau on utilise Array.Resize
int [] monArray = { 1, 2, 3 };
string[] tonArray = { "Tom", "Dick", "Harry" };
Array.Resize(ref monArray, 6);
Array.Resize(ref yourArray, 6);
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 36
3.4.3 La boucle foreach
Une boucle foreach permet de parcourir les éléments d’une liste, a fortiori d’un tableau. Sa
syntaxe est la suivante :
foreach (type identificateur in expression) instruction(s);
Exemple:
int[,] monIntArray = { {1, 3, 5},{2, 4, 6} };
Console.WriteLine("nb d’éléments:{0}", monIntArray.Length
foreach(int i in IntArray)
Console.Write("{0} ", i);
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 37
4 Classes et objets
4.1 Introduction
4.1.1 Limites de l’approche procédurale
Les données et fonctions sont définies séparément. On doit donc passer les données en
paramètre à chaque fonction. Ceci pose :
• Le problème de la protection des données puisque les champs sont accessibles à tous ;
• Le problème de l’encapsulation en général.
4.1.2 Encapsulation et concept d’objet
En conception orientée objet, les données et les fonctions qui les manipulent sont regroupées
dans une même entité : l’objet. Les détails d’implémentation sont donc cachés et l’extérieur n’a
accès aux données qu’au travers de l’interface de l’objet.
Les avantages sont nombreux :
• Abstraction de données,
• Modularité,
• Facilités de modification (couplage faible),
• Réutilisabilité,
• Lisibilité des programmes: détails d’implémentation cachés.
4.2 Classes
Ce sont des types référence définis par l’utilisateur. Elles sont similaires aux classes C++ ou
Java. Leurs caractéristiques sont :
• L’héritage simple sur la classe ;
• Elles peuvent implémenter de multiples interfaces ;
• Le contrôle de l’accès aux membres se fait par les modificateurs d’accès :
public, private, internal, protected, protected internal
• Le mode par défaut est private ;
• Les membres des classes sont des :
• Constantes, champs (fields), méthodes, opérateurs (constructeurs et destructeurs);
• Propriétés, indexeurs, évènements ;
• Membres par classe (static) ou par instance ;
• Les classes sont instanciées par l’opérateur new.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 38
4.2.1 Ajout d’une classe dans VS
4.2.2 Exemple de classe
Définition de variables et instanciation
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 39
4.2.3 Niveaux d’accessibilité des classes
Une classe peut avoir l’un des niveaux d’accessibilité suivants :
Public : pas de restriction d’accès,
Internal : accès limité aux classes du même assembly (par défaut).
Les classes imbriquées peuvent également avoir l’un des niveaux d’accessibilité suivants :
private: accès limité à la classe « englobant »
protected: accès limité à la classe englobant et aux classes dérivées
protected internal: accès limité aux classes de l’assembly et aux classes dérivées
qui sont dans un autre assembly.
Exemple d’accessibilité :
class globale
{
protected class Point
{
public int x; //champs accessibles aux autres
// classes.
public int y;
}
class Program
{
static void Main(string[] args)
{
Point p1 = new Point();
p1.x = 33;
p1.y = 22;
Console.WriteLine("x = {0}, y = {1}", p1.x, p1.y);
}
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 40
4.2.4 Variables membres (champs)
Une variable membre est caractérisée par :
• Un niveau d’accessibilité
• Un type
• Une valeur par défaut (optionnelle)
Exemple:
protected string nomEmploye = "Durand";
Une variable peut être déclarée « static ». Elle est alors partagée entre les différentes instances
de la classe.
Exemple :
public static string nomCompagnie;
Une variable peut-être déclarée « readonly » pour empêcher sa modification après la
construction de l’objet. Une valeur ne peut lui être assignée que lors de sa déclaration ou dans le
constructeur.
Exemple:
public readonly int age = 45;
Une constante doit avoir sa valeur fixée à la compilation.
Exemple:
protected const int NBMAX = 100;
4.2.5 Fonctions membres et méthodes
Les fonctions membres (méthodes) sont déclarées et implémentées au même endroit. Elles sont
caractérisées par :
• Un niveau d’accessibilité,
• Un type de retour (éventuellement void) et
• Une liste de paramètres.
Exemple :
public int MaMethode() {}
L’accessibilité est private par défaut. Une méthode peut être déclarée « static ». On
l’appelle alors via le nom de la classe et non pas via une instance.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 41
Depuis la version 4, il y a des paramètres par défaut en C#. On peut donc définir une fonction en
précisant des valeurs par défaut à certains paramètres, comme dans l’exemple :
void optMethode(int un, double deux=0.0, string trois="salut")
Un appel possible à cette méthode est :
optMethode(99);
Par défaut, les paramètres sont passés par valeur. Il existe cependant un autre type de passage de
paramètres via ref.
• Surcharge de méthodes : la signature d’une méthode est caractérisée par son nom et la
signature des paramètres (y compris le type de passage des paramètres).
Une méthode peut également être déclarée « sealed », ce qui empêche de la surcharger dans
une classe dérivée.
4.2.6 Les propriétés
Les propriétés sont un mécanisme pour exposer des données. De l’extérieur, cela ressemble à une
variable publique. Elles permettent de cacher les détails d’implémentation et d’ajouter un
traitement additionnel (validation, tracing, …).
Exemple:
Depuis C# 3.0 il est possible d'implémenter les propriétés automatiquement ; ce qui rend la
déclaration de propriété plus concise quand aucune logique supplémentaire n'est requise dans les
accesseurs de propriété.
public string Nom { get; set; }
public int ClientID { get; set; }
Depuis C#6, il est possible de les initialiser :
public string Prenom { get; set; } = "Jane";
Public class Personne
{
private string nom;
public string Nom
{
get {return nom;}
set {nom = value;}
}
}
Personne unePersonne = new Personne ();
unePersonne.Nom = "Dupont";
Création automatique dans VS:
Bouton droit  Refactoriser  Encapsuler le champ.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 42
4.2.6.1 Propriétés statiques
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 43
4.2.6.2 Propriétés readonly
On peut définir une propriété en lecture seule en ne fournissant que le code du get :
Les propriété auto-implémentée en lecture seule ne peuvent être initialisées que dans leurs
déclarations ou dans les constructeurs.
En C#6 il est possible d’initialiser une propriété auto-implémentée dans sa déclaration en
utilisant la syntaxe suivante :
Type PropertyName { get; set; } = initializer;
public class Produit
{
public decimal Prix { get; set; } = 10.25;
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 44
4.2.6.3 Accessibilité des accesseurs
Chaque accesseur a sa propre accessibilité :
public string NomEmploye
{
get { return nomEmploye;}
protected set { nomEmploye = value; }
}
Les modificateurs d'accès ne sont autorisés que sur l'un des accesseurs – habituellement set.
Si l’on a qu’un seul accesseur, alors il n’y a pas de modificateur d'accès sur l'accesseur.
4.2.7 Constructeur et destructeur
Le constructeur et le destructeur sont deux méthodes particulières qui sont appelées
respectivement à la création et à la destruction d'un objet.
4.2.7.1 Constructeurs
Caractéristiques du constructeur :
• Un constructeur est une fonction membre dont le nom est le même que celui de la
classe ;
• Un constructeur n’a pas de type ;
• On peut avoir plusieurs constructeurs ;
• En fonction du nombre et du type des arguments passés à l’appel, le bon constructeur
est choisi.
Il y a 3 catégories de constructeurs :
• Constructeurs d’instance :
Ce sont les constructeurs les plus fréquents et parfois appelés juste ‘constructeurs’. Ils portent le
même nom que la classe, et sont invoqués lors de la création d’un nouvel objet.
• Constructeurs privés :
Ils ne sont utilisés qu’avec des classes qui ne contiennent que des membres statiques.
• Constructeurs statiques :
Ils sont utilisés pour initialiser une classe. Ils sont appelés avant la création de tout objet et avant
tout appel à un membre statique de la classe.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 45
Exemple de constructeur d’instance
class Point
{
public int x, y;
// Constructeur par défaut :
public Point()
{
x = 0;
y = 0;
}
// Un constructeur avec des paramètres
public Point(int x1, int y1)
{
x = x1;
y = y1;
}
}
class MaClasse
{
static void Main()
{
Point p1 = new Point();
Point p2 = new Point(2, 10);
Console.WriteLine("Premier Point : ({0}, {1})", p1.x, p1.y);
Console.WriteLine("Deuxième Point : ({0}, {1})", p2.x, p2.y);
}
}
4.2.7.2 Mot clé « this »
this est une référence sur l’objet courant qui est utilisée pour accéder aux données membres
dans un constructeur d'instance (ou des méthodes accesseurs). Dans ce cas, on peut utiliser les
mêmes noms pour les champs et les paramètres. Ce mot-clé ne peut être utilisé avec les
constructeurs statiques ou les champs.
4.2.7.3 Constructeurs privés
Ils sont utilisés avec des classes qui ne contiennent que des membres statiques.
Les autres classes, sauf celles imbriquées dans la même classe, ne sont pas autorisées à créer des
instances de cette classe.
public class MaClasse
{
private MaClasse() {} // private constructor
public string nomCompagnie;
public string dateEmbauche;
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 46
Le constructeur privé est un constructeur vide dont le travail est d'empêcher la génération d'un
constructeur par défaut pour la classe. Ainsi, l’instruction :
MaClasse mc = new MaClasse();
Provoque une erreur de protection.
Il est préférable de déclarer static une classe qui ne contient que des membres statiques.
4.2.7.4 Constructeurs statiques
Les constructeurs statiques sont utilisés pour initialiser une classe ou n'importe quelle donnée
statique, ou pour effectuer une action particulière devant être effectuée une seule fois. Ils sont
appelés avant la création de tout objet et avant tout appel à un membre statique de la classe.
class MaClasse
{
// Constructeur statique
static MaClasse()
{
Console.WriteLine("Je suis le constructeur statique! " +
"Je suis appelé automatiquement!");
}
public void MaMethode()
{
Console.WriteLine("Je suis MaMethode. J'ai été appelée après " +
"le constructeur statique!");
}
}
public class MaClasse
{
public static void Main()
{
MaClasse monObjet = new MaClasse();
monObjet.MaMethode();
}
}
4.2.7.5 Héritage
class MaClasseDerivee: MaClasseBase
{
// ...
}
La classe, MaClasseDerivee hérite de la classe MaClasseBase.
Le symbole (:) est utilisé entre le nom de la classe dérivée et le nom de la classe de base.
L’hérédité signifie que la classe dérivée contient tous les membres de la classe de base.
On peut également ajouter de nouveaux membres aux membres hérités.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 47
4.2.7.6 Règles de contrôle de l'héritage:
Tous les membres de la classe de base sont héréditaires (sauf les constructeurs d’instance, les
destructeurs et les constructeurs statiques).
Un membre dans la classe dérivée avec le même nom que dans la classe de base, cache ce dernier.
Le membre de la classe de base n'est pas accessible par l'intermédiaire de la classe dérivée.
Les fonctions membres dans la classe de base peuvent être remplacées par celles de la classe
dérivée: polymorphisme.
Une classe peut hériter d'une classe seulement (pas d’héritage multiple). Cependant, elle peut
implémenter plus d'une interface.
Les structures ne peuvent pas hériter de classes ou d’autres structures ni être héritées, mais elles
peuvent implémenter des interfaces.
Exemple
class Citoyen
{
string identifiant = "111-2345-H";
string nom = "Pille Mandla";
public void GetInfosPersonnelles()
{
Console.WriteLine("Nom: {0}", nom);
Console.WriteLine("Numéro de carte : {0}", identifiant);
}
}
class Employe : Citoyen
{
string nomCompagnie = "Technology Group Inc.";
string idCompagnie = "ENG-RES-101-C";
public void GetInfo()
{
// Appel à la méthode GetPersonalInfo de la classe de base:
Console.WriteLine("Informations du Citoyen :");
GetInfosPersonnelles();
Console.WriteLine("nInformation sur son emploi :");
Console.WriteLine("Nom Compagnie : {0}", nomCompagnie);
Console.WriteLine("ID Compagnie : {0}", idCompagnie);
}
}
class MainClass
{
public static void Main()
{
Employe E = new Employe();
E.GetInfo();
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 48
4.2.7.7 Les destructeurs
Les destructeurs sont utilisés pour détruire les objets. Un destructeur est déclaré ainsi:
~MaClasse()
{
// Instructions de destruction.
}
Ils portent le même nom que la classe, mais sont précédés par ~.
Exemple de destructeur
class Parent // parents
{
~Parent()
{
Console.WriteLine("On appelle le destructeur de Parent.");
}
}
class Enfant : Parent // enfants
{
~Enfant()
{
Console.WriteLine("On appelle le destructeur de Enfant.");
}
}
class GrandEnfant : Enfant // grand enfants
{
~GrandEnfant()
{
Console.WriteLine("On appelle le destructeur de GrandEnfant.");
}
}
public class MaClasse
{
public static void Main()
{
GrandEnfant monObjet = new GrandEnfant();
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 49
4.2.8 Classes partielles
Il est possible de fractionner la définition d'une classe ou d'un struct, ou d'une interface sur
deux fichiers sources ou plus. Chaque fichier source contient une section de la définition de
classe, et toutes les parties sont combinées lorsque l'application est compilée.
public partial class Employee
{
public void DoWork() { }
}
public partial class Employee
{
public void GoToLunch() { }
}
4.2.9 Classes finales
Lorsqu'il est appliqué à une classe, le modificateur ‘sealed’ empêche les autres classes d'en
hériter.
class A
{}
sealed class B : A
{}
Dans cet exemple, la classe B hérite de la classe A, mais aucune classe ne peut hériter de B.
4.3 Les structures : Struct
Les structures sont similaires aux classes, mais diffèrent par un certain nombre de
caractéristiques :
- Ce sont des types valeur définis par l’utilisateur donc alloués sur la pile ;
- Elles héritent toujours d’objet ;
- Elles sont idéales pour des objets ‘légers’ ;
- int, float, double, etc., sont des structures ;
- Elles permettent la définition de types primitifs par l’utilisateur
Complex, point, rectangle, color, rational
- Elles supportent l’héritage multiple des interfaces ;
- Elles ont les même membres que les classes ;
- Les contrôles d’accès sont : public, internal, private;
- Elles sont Instanciées par l’opérateur new;
- Elles sont implicitement sealed, ce qui veut dire qu’il est impossible d'en hériter.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 50
Exemple
4.3.1 Classes et Structures
class CPoint { int x, y; ... }
struct SPoint { int x, y; ... }
CPoint cp = new CPoint(10, 20);
SPoint sp = new SPoint(10, 20);
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 51
4.4 Visual Studio et les classes
4.4.1 Diagramme de classes
Il est possible de créer ou de visualiser un diagramme de classes dans Visual studio. Celui-ci est
accessible à partir de l’explorateur de solutions. Il permet de rajouter des classes et leurs
membres.
4.4.2 Documentation XML
On peut créer automatiquement une documentation XML pour documenter les classes et leurs
membres. Pour cela on suit les étapes suivantes :
Projet  Propriétés  Onglet Générer  Boîte sortie : spécifier un nom de fichier XML de
documentation.
Le fichier XML sera généré à la compilation et accessible à partir du répertoire du projet.
Les balises de documentation précèdent n’importe quel membre du projet et sont introduites par
///.
Exemples de balises proposées:
<summary>, <para>, <param>, <description>, <permission>,
<remarks>, …
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 52
4.5 Classes .NET d’usage courant
4.5.1 Fonctions mathématiques
Classe: System.Math
Cette classe ne contient que des champs et méthodes statiques. Parmi les méthodes disponibles
on peut trouver :
Méthodes numériques multi-types: Abs, Min, Max et Sign
Méthodes trigonométriques: Cos, Sin, …
Méthodes puissances : log et exp
Round, Ceiling, Floor
Exemple:
4.5.2 Dates et intervalles de temps
2 classes sont disponibles :
System.DateTime dont l’instance est une date.
System.TimeSpan: dont l’instance est un intervalle de temps.
Exemples:
DateTime t = new DateTime(2014,10,19,18,0,0);
string strDate = t.ToShortDateString();
string strTime = t.ToShortTimeString();
int day = t.DayOfYear;
DateTime now = DateTime.Now;
DateTime dans1Mois = t.AddMonths(1);
DateTime t2 = Convert.ToDateTime("2014/10/20");
int nbJours = DateTime.DaysInMonth(2014,2);
4.5.3 Accès au système de fichiers
L’espace de noms System.IO contient les classes permettant de manipuler les répertoires et les
fichiers. Parmi les classes intéressantes on dénombre les classes pour :
• La manipulation des répertoires: Directory et DirectoryInfo
• La manipulation des fichiers: File et FileInfo
• La manipulation des chemins d’accès: Path
• La lecture / écriture dans des streams: StreamWriter et StreamReader, …
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 53
Exemple:
string srcPath = "c:temp";
if (!Directory.Exists(srcPath))
{
Console.WriteLine("Le repertoire n'existe pas!");
}
else
{
string[] lstRepertoires = Directory.GetDirectories(srcPath);
string[] lstFichiers = Directory.GetFiles(srcPath);
DirectoryInfo df = new DirectoryInfo(srcPath);
foreach (FileInfo fileinfo in df.GetFiles())
Console.WriteLine(fileinfo.FullName);
string testFilePath = srcPath + "test.txt";
StreamWriter sw = File.CreateText(testFilePath);
sw.WriteLine("Test ....");
sw.Close();
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 54
5 Les fonctions membres
5.1 Définition des fonctions membres
Tous les membres d'une classe ou d’une structure (à l'exception des champs et des constantes)
sont des fonctions membres :
Méthodes
Propriétés
Événements
Indexeurs
Opérateurs définis par l’utilisateur
Constructeurs
Destructeurs
• Le polymorphisme
Soit, par exemple, une méthode appelée DessineFenetre. On peut associer cette méthode
avec divers objets qui représentent les différents types de fenêtres.
Selon l'objet associé à la méthode, le résultat va être différent.
monBouton.DessineFenetre(); // dessine un bouton
monMsg.DessineFenetre(); // dessine une message box
maSurface.DessineFenetre(); //dessine une fenêtre à peindre
5.2 Méthodes virtuelles et redéfinies
Pour utiliser les méthodes polymorphes on déclare la méthode DessineFenetre() avec le
mot-clé virtual dans la classe de base:
public virtual void DessineFenetre() {
// La définition de la méthode est dans la classe de base.
}
Ensuite, dans chacune des classes qui héritent de la classe de base, on déclare une méthode
DessineFenetre() en utilisant le mot-clé override:
public override void DessineFenetre() {
// La définition de la méthode est dans une des classes dérivées.
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 55
5.2.1 Redéfinition de méthode
On peut redéfinir une autre méthode qui a le même nom, la signature et la même accessibilité que
dans la classe de base. Quand on redéfinit une méthode, on peut changer son comportement
d'origine dans la classe dérivée. Une méthode redéfinie peut redéfinir toutes les méthodes
déclarées avec les modificateurs suivants:
virtual
abstract
override
Pour qu’une méthode redéfinisse celle de la classe de base, il faut modifier sa déclaration avec le
mot-clé override.
Une méthode abstraite est implicitement virtuelle, et donc peut-être redéfinie sans utiliser le
modificateur virtual (elle ne peut pas de toute façon utiliser ce modificateur).
On ne peut pas utiliser le modificateur virtual avec les modificateurs suivants:
static, abstract ou override.
On ne peut pas combiner le modificateur override avec les modificateurs suivants:
static, abstract, virtual ou new.
5.2.2 Appel aux Membres de la Classe de base
Si on désire appeler une méthode redéfinie de la classe de base on utilise le mot-clé base.
base.GetInformation();
On ne peut pas utiliser le mot-clé base dans une méthode statique.
S’il est nécessaire de construire l'objet de la classe de base avant de construire l'objet de la classe
dérivée, on appelle le constructeur ainsi :
public MaDerivee(int x) : base(x)
{
// ...
}
Ceci est le constructeur de la classe MaDerivee, qui construit l'objet de la classe de base à la
volée.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 56
5.2.3 Redéfinition des méthodes Virtuelles de la Classe de Base
// La classe de base :
public class AiresClass
{
// champs:
protected double x, y;
// Constructeurs:
public AiresClass()
{ }
public AiresClass(double x, double y)
{
this.x = x;
this.y = y;
}
// Méthodes:
public virtual double Aire()
{
return 0;
}
}
// La classe Point utilise un constructeur
sans paramètres :
class Point : AiresClass
{
public Point() : base()
{ }
}
// La classe Cercle :
class Cercle : AiresClass
{
public Cercle(double r): base(r, 0)
{ }
public override double Aire()
{
// L'aire d'un cercle.
// Le rayon est représenté par x:
return Math.PI * x * x;
}
}
// La classe Sphere :
class Sphere : AiresClass
{
public Sphere(double r): base(r, 0)
{ }
public override double Aire()
{
// Le rayon est représenté par x:
return 4 * Math.PI * x * x;
}
}
// La classe Cylindre:
class Cylindre : AiresClass
{
public Cylindre(double r, double h)
: base(r, h)
{ }
public override double Aire()
{ // x : rayon y : hauteur
return 2*Math.PI *x*x + 2*Math.PI*x*y;
}}
class MaClasse
{
public static void Main()
{
// Lire les valeurs au clavier et les convertir:
Console.Write("Entrer le rayon: ");
double rayon = Convert.ToDouble(Console.ReadLine());
Console.Write("Entrer la hauteur: ");
double hauteur = Convert.ToDouble(Console.ReadLine());
// Créer les objets:
Point monPoint = new Point();
Cercle monCercle = new Cercle(rayon);
Sphere maShpere = new Sphere(rayon);
Cylindre monCylindre = new Cylindre(rayon, hauteur);
// Afficher les résultats:
Console.WriteLine("Aire du point = {0:F2}",
monPoint.Aire());
Console.WriteLine("Aire du cercle = {0:F2}",
monCercle.Aire());
Console.WriteLine("Aire de la sphère = {0:F2}",
maShpere.Aire());
Console.WriteLine("Aire du cylindre = {0:F2}",
monCylindre.Aire());
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 57
5.3 Classes et méthodes abstraites
Le but d'une classe abstraite est d’être héritée par d'autres classes. Elle ne peut donc pas être
instanciée. Une méthode abstraite est, par défaut, une méthode virtuelle. Elle ne peut exister qu'à
l'intérieur d'une classe abstraite.
abstract class MaBaseClasse // classe abstraite
{
public abstract void MaMethode(); // méthode abstraite
...
}
Les mots clés suivants ne sont pas permis dans la déclaration d’une méthode abstraite : static,
virtual.
Exemple :
// Class abstraite :
abstract class ClassDeBase
{
// Champs:
protected int nombre = 100;
protected string nom = "Dale Sanders";
// Méthode abstraite :
public abstract void MaMethode();
// Propriétés abstraite :
public abstract int Nombre
{ get; }
public abstract string Nom
{ get; }
}
// Hériter de la classe:
class MaClasseDerivee : ClassDeBase
{
// Surcharge des propriétés:
public override int Nombre
{
get { return nombre; }
}
public override string Nom
{
get { return nom; }
}
// Surcharge de la méthode:
public override void MaMethode()
{
Console.WriteLine("Nombre = {0}",
Nombre);
Console.WriteLine("Nom = {0}", Nom);
}
}
class ClassePrincipale
{
public static void Main()
{
MaClasseDerivee monObjet = new MaClasseDerivee();
monObjet.MaMethode();
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 58
5.4 Surcharge de méthodes
La surcharge de méthodes consiste à donner le même nom à plus d'une méthode et laisser le
compilateur charger la méthode appropriée en fonction du nombre et du type de paramètres.
Exemple: La fonction est surchargée
int AuCarre(int x)
double AuCarre (double f)
Elle peut être appelée de 2 manières différentes :
AuCarre (3.25);
AuCarre (44);
Note: Le lien entre la méthode spécifique et l'appel est fait au moment de la compilation, c’est ce
que l’on appelle une liaison statique (ou anticipée).
Un autre cas est possible quand les paramètres sont de même type mais en nombres différents.
void MaMethode(int m1) { }
void MaMethode(int m2, int m3) { }
Exemple
class MaClasse
{
// Paramètre de type string :
static void MaMethode(string s1)
{
Console.WriteLine(s1);
}
// Paramètre de type entier :
static void MaMethode(int m1)
{
Console.WriteLine(m1);
}
// Paramètre de type double :
static void MaMethode(double d1)
{
Console.WriteLine(d1);
}
static void Main()
{
string s = "Voilà ma chaîne";
int m = 134;
double d = 122.67;
MaMethode(s);
MaMethode(m);
MaMethode(d);
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 59
5.5 Passage de Paramètres
Il y a deux façons de passer un paramètre à une méthode :
• par valeur (passage par défaut) ou
• par référence.
5.5.1 Passage par référence
Le passage de paramètres par référence permet de modifier les valeurs des variables de manière
persistante. Pour passer un paramètre par référence, on déclare le paramètre avec le mot-clé ref.
Exemple
// Exemple Permuter
class MaClasse
{
static void Permuter(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
static void Main()
{
int x = 25;
int y = 33;
Console.WriteLine("Avant la permutation: x={0}, y={1}", x, y);
Permuter(ref x, ref y);
Console.WriteLine("Après la permutation: x={0}, y={1}", x, y);
}
}
Il y a trois modificateurs de paramètres, qui permettent la modification de la valeur des variables
après le retour à la méthode appelante. Ces trois modificateurs sont : ref, out et params.
Lorsqu’on utilise ref pour passer une variable à une méthode, la variable doit être initialisée en
premier, sinon on génère une erreur du compilateur.
Le modificateur out ne nécessite pas l'initialisation de la variable avant de la transmettre à la
méthode, mais l'initialisation doit se faire dans la méthode elle-même.
private void methodeTest(out int resultat) {}
L’appel se fait par:
methodeTest(out n);
Le mot clé params est utilisé avec des tableaux. Il permet de transmettre n'importe quel
nombre de paramètres à une méthode sans qu’il soit nécessaire de les déclarer dans un tableau.
Ce mot clé est requis uniquement dans la déclaration de la méthode.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 60
Par exemple soit la fonction :
static void MaMethode(params object[] monObjArray)
L’appel à la méthode se fait par :
MaMethode(123, 'A', "Ma chaine originale");
Les paramètres passés dans cet appel sont tous du type object, ce qui signifie qu’ils peuvent
inclure tous les types hérités de la classe object.
Exemple :
public class MaClasse
{
// Déclaration de MaMethode qui utilise des paramètres entiers :
public void MaMethode(params int[] monIntArray)
{
Console.WriteLine("Ma liste d'entiers originale:"); // Liste originale
for (int i = 0; i < monIntArray.Length; i++)
Console.WriteLine(monIntArray[i]);
Console.WriteLine();
monIntArray[1] = 555; // Changer le 2ème élément
Console.WriteLine("Ma liste d'entier après le changement:"); //après le changement
for (int i = 0; i < monIntArray.Length; i++)
Console.WriteLine(monIntArray[i]);
Console.WriteLine();
}
// Déclaration de MaMethode qui utilise des paramètres objets :
public void MaMethode(params object[] monObjArray)
{
Console.WriteLine("Ma liste d'objets originale:"); //avant le changement
for (int i = 0; i < monObjArray.Length; i++)
Console.WriteLine(monObjArray[i]);
Console.WriteLine();
// Changer le 3ème élément:
monObjArray[2] = "Ma nouvelle chaîne";
Console.WriteLine("Ma liste d'objets après le changement:"); //après le changement:
for (int i = 0; i < monObjArray.Length; i++)
Console.WriteLine(monObjArray[i]);
Console.WriteLine();
}
}
class MainClass
{
static void Main()
{
// Déclaration d'un tableau d'objets:
object[] maObjListe = new object[] { 123, 'A', "Mon ancienne chaine" };
MaClasse mc = new MaClasse();
// Passer 4 entiers à la "première" MaMethode:
mc.MaMethode(11, 22, 33, 44); // utiliser des paramètres numériques
// Passer un tableau d'objets à la "2ème" MaMethode
mc.MaMethode(maObjListe); // utiliser un tableau d'objets
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 61
5.6 Propriétés sous la forme d’expressions
C# 6 a introduit une syntaxe concise pour :
• Méthodes qui contiennent seulement une instruction return ;
• Propriétés read-only dans lesquelles get contient seulement un return ;
• Méthodes qui contiennent une instruction simple.
Exemple :
La fonction :
static int Cube(int x)
{
return x * x * x;
}
s’écrira en C#6
static int Cube(int x) => x * x * x;
5.7 Les indexeurs
Les indexeurs, permettent de manipuler des classes comme des tableaux ou des collections. On
peut donc accéder aux éléments de l’indexeur en utilisant les crochets ([]).
Un indexeur est similaire aux propriétés puisqu’il peut aussi utiliser les accesseurs get et set
pour exprimer ses caractéristiques.
La déclaration d’un indexeur est de la forme:
indexer-type this [parameter-type parameter]
{
get {};
set {};
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 62
où:
indexer-type est le type de l’indexeur.
parameter-type est le type du paramètre.
parameter est un paramètre ou une liste de paramètres
Exemple
class MaClasse
{
private string[] monTableau = new string[10];
// Déclaration de l'indexeur :
public string this[int index]
{
get
{
return monTableau [index];
}
set
{
monTableau [index] = value;
}
}
}
public class MainClass
{
public static void Main()
{
MaClasse s = new MaClasse();
// Utiliser l'indexeur pour initialiser les éléments #1 et #2:
s[1] = "Tom";
s[2] = "Edison";
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Element #{0}={1}", i, s[i]);
}
}
}
5.7.1 Utilisation des indexeurs
Il est courant d'utiliser les accesseurs set et get pour contrôler les limites de l'indexeur et éviter
les erreurs. Par exemple:
if (!(index < 0 || index >= 10))
// ...
Il est permis aux interfaces d'avoir des indexeurs. Ils sont déclarés de la même manière avec les
exceptions suivantes:
- Les indexeurs des interfaces n’utilisent pas les modificateurs.
- Il n'y a pas d’implémentation d’accesseurs dans les interfaces.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 63
5.8 La surcharge des opérateurs
La surcharge permet d’assigner de nouveaux rôles pour certains opérateurs. Par exemple, on peut
surcharger l’opérateur ‘+’ pour la classe Point :
public static Point operator+(Point p1, Point p2)
{
// Implémentation de l’opérateur +
// Voir exemple
}
D’autres exemples sont : operator-– , operator==
Exemple
public class Point
{
public int x;
public int y;
// Constructeur:
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Surcharge de l'opérateur +:
public static Point operator +(Point p1, Point p2)
{
// Retourner la somme comme un point:
return new Point(p1.x + p2.x, p1.y + p2.y);
}
static void Main()
{
Point p1 = new Point(15, 33);
Point p2 = new Point(10, 12);
// Ajouter les 2 obbjets Point utilisant l'opérateur + surchargé:
Point sum = p1 + p2;
// Afficher les objets:
Console.WriteLine("Point #1: ({0}, {1})", p1.x, p1.y);
Console.WriteLine("Point #2: ({0}, {1})", p2.x, p2.y);
Console.WriteLine("Sum of the two points: ({0}, {1})", sum.x, sum.y);
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 64
5.8.1 Opérateurs surchargeables
5.8.2 Redéfinir la méthode ToString()
Cette redéfinition est très utile pour l’affichage. Par exemple, au lieu de :
Console.WriteLine("Point #1: ({0},{1})", p1.x, p1.y);
On voudrait :
Console.WriteLine("Point #1: {0}", p1);
Pour cela on surcharge la méthode ToString(). On réalise la surcharge de la manière
suivante :
// Surcharge de la méthode ToString
public override string ToString()
{
return (String.Format("({0}, {1})", x, y));
}
5.9 Les attributs
Les attributs sont des informations additionnelles qui permettent de modifier les déclarations des
entités de programme (types, membres, paramètres, etc., …). Ils servent à différentes choses
comme par exemple marquer une méthode comme obsolète, indiquer une compilation
conditionnelle, …
Ils sont dérivés de la classe abstraite System.Attribute. L’attribut est mis entre [].
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 65
Exemple:
[method: DllImport("user32.dll")]
C’est un attribut qui permet d’utiliser du code ‘unsafe’.
Les éléments cibles des attributs sont:
Assembly, field, event, method, parameter, property, return, type
Autres exemples d’attributs
Obsolète:
[Obsolete("Vous devriez coder en Csharp! ", true)]
public void CodeEnCPlusPlus()
{
// Le corps de la méthode obsolète.
}
Quand on compile cette méthode, le compilateur génère l’erreur : 'MaClasse.CodeEnCPlusPlus()' is
obsolete: ‘Vous devriez coder en Csharp!‘. Si le 2ème paramètre est à false, le compilateur génère un
warning, sinon c’est une erreur fatale.
Conditionnel:
[Conditional("MACONSTANTE")]
public void MaMethode(string s) {}
MaMethode n’est exécutée que si la constante MACONSTANTE est définie avec une
directive: #define MACONSTANTE
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 66
6 Les Exceptions
6.1 Erreurs et exceptions
En C#, une exception est un objet de la classe System.Exception ou une de ses
sous-classes. Les mots-clés utilisés pour traiter les exceptions sont : throw, catch, et finally.
La gestion des exceptions requiert l’utilisation des mots-clés :
- throw: Pour lancer ou relancer une exception.
- try-catch: Pour capturer et traiter une exception.
- try-finally: Pour libérer les ressources après le lancement de l’exception
indépendamment de sa capture.
- try-catch-finally: Pour capturer et traiter une exception et libérer les ressources.
6.2 Lancer une Exception
throw [expression];
où:
expression est l’exception.
6.3 Exemples d’exceptions :
- InvalidCastException
- OverFlowException
- ArgumentNullException
- ArithmeticException
- DivideByZeroException
Par exemple, l’appel à la méthode System.IO.File.OpenRead() peut provoquer le
lancement des exceptions suivantes :
- SecurityException
- ArgumentException
- ArgumentNullException
- PathTooLongException
- DirectoryNotFoundException
- UnauthorizedAccessException
- FileNotFoundException
- NotSupportedException
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 67
Exemple
string monString = "Salut.";
// Afficher la chaîne
Console.Write("La chaîne est {0}", monString);
monString = null;
if (monString == null)
{
throw new ArgumentNullException(); // lancer l'exception
}
// Cette ligne n'est pas exécutée:
Console.Write("monString est null.");
6.4 Capturer une Exception
Pour capturer une exception, le code suspect est mis dans un bloc try :
try
{// Le code à protéger. }
Le gestionnaire de l’erreur est mis dans un bloc de capture:
catch [(declaration)]
{ // Le code du gestionnaire d’exception. }
Où declaration est la déclaration de l’objet exception (optionnel).
Exemple
class MaClasse
{
public void MaMethode(string monString)
{
if (monString == null)
// Lancer l'exception
throw (new ArgumentNullException());
}
public static void Main()
{
MaClasse MaClasse = new MaClasse();
// Le code suspect
try
{
string monString = null;
MaClasse.MaMethode(monString);
}
// Traitement de l'exception:
catch (Exception e)
{
Console.WriteLine("L'exception suivante est capturée : n{0}", e);
}
// Continuer après le traitement de l'exception:
Console.WriteLine("Le programme continue ...");
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 68
6.5 Organisation des gestionnaires
Quand on utilise plus d'un bloc catch, il est important de capturer les exceptions spécifiques
avant les moins spécifiques. Si un gestionnaire adéquat n’existe pas dans la méthode actuelle, le
moteur d’exécution cherche dans les autres méthodes.
Exemple:
catch (ArithmeticException e) // premier gestionnaire
{
//...
}
...
...
catch (Exception e) // dernier gestionnaire
{
// ...
}
6.6 Instruction try-finally
L’utilisation du mot-clé finally permet d’introduire un code de nettoyage qui sera exécuté
dans tous les cas. Cela permet, par exemple de libérer des ressources.
try
{ // bloc-try }
finally
{ // bloc-finally }
Où :
try-block : contient le code suspect à essayer
finally-block : contient les instructions de ‘nettoyage’ à exécuter indépendamment
de l'exception lancée.
6.7 Instruction try-catch-finally
try
{ // bloc-try }
catch
{ // bloc-catch }
finally
{ // bloc-finally }
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 69
6.8 Exceptions personnalisées
On peut créer une exception personnalisée en la déclarant comme dérivée de
ApplicationException.
Avantage : personnaliser le texte du gestionnaire pour expliquer l’erreur.
class MonExceptionPersonnalisee: ApplicationException
Un constructeur avec un string comme paramètre est utilisé pour envoyer le message à la
classe héritée:
MonExceptionPersonnalisee(string message): base(message)
{ }
Exemple
// Une exception personnalisée
public class MonException : Exception
{
// Constructeur de la classe MonException:
public MonException(string message): base(message)
{ }
}
static void Main()
{
// Créer une instance de MonException:
MonException e = new MonException("qui contient mon message personnalisé");
try
{
throw e; // Lancer l'exception
}
catch (MonException)
{
// Capturer l'exception:
Console.WriteLine("L'exception {0} a été traitée avec succès.", e);
}
catch
{
Console.WriteLine("Exception inconnue traitée.");
}
finally
{
// Le code dans ce bloc est toujours exécuté:
Console.WriteLine("Le programme continue ici.");
}
// Afficher un message après le bloc finally :
Console.Write("Fin d'exécution.");
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 70
6.9 Relancer une exception
Cela consiste à envoyer une exception à une autre méthode ou au Main pour avoir plus de
détails. Pour cela on utilise throw sans paramètres:
catch
{ throw; }
Le bloc de capture peut ajouter un message.
Exemple
static void Main()
{
maClasse mc = new maClasse();
try
{
mc.MaMethode1(); // évènement #1
}
catch (Exception e)
{
Console.WriteLine("Capturée dans le Main: {0}", e); // évènement #6
Console.WriteLine("On continue le nettoyage ...");
}
}
public void MaMethode1()
{
try
{
MaMethode2(); // évènement #2
}
catch (Exception)
{
Console.WriteLine("Capturée dans MaMethode1"); // évènement #4
Console.WriteLine("Nettoyage ...");
// Relancer la même exception:
throw; // évènement #5
}
}
public void MaMethode2()
{
throw new Exception("lancée par MaMethode2"); // évènement #3
}
6.10 Utilisation de StackTrace
StackTrace permet de garder la trace de l’exception au fur et à mesure qu’elle est capturée.
catch (Exception e)
{
Console.WriteLine("Capturée dans le Main: {0}", e.StackTrace);
Console.WriteLine("On continue le nettoyage ...");
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 71
6.11 Opérateur de condition null : ?. (C#6)
Le code suivant
{
var exampleObject = new ExampleClass();
try
{
exampleObject.SomeMethod();
}
finally
{
if (exampleObject != null)
{
exampleObject.Dispose();
}
}
}
peut se réécrire en C#6 :
{
var exampleObject = new ExampleClass();
try
{
exampleObject.SomeMethod();
}
finally
{
exampleObject?.Dispose();
}
}
6.12 Filtres d’Exceptions (C#6)
C# 6 a introduit des filtres d’exceptions qui permettent de capturer une basée sur un type et une
condition qui spécifiée dans une clause ‘when’.
catch(ExceptionType name) when(condition)
ou encore dans une exception généralisée:
catch when(condition)
Exemple:
try
{
Console.WriteLine("Filtres d'exception.");
throw new Exception();
}
catch (Exception ) when (
(DateTime.Now.DayOfWeek == DayOfWeek.Saturday) ||
(DateTime.Now.DayOfWeek == DayOfWeek.Sunday))
{
Console.WriteLine("Capturée.");
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 72
6.13 Nameof (C#6)
Utilisé pour obtenir le nom d’une variable sous la forme d’un string.
Ce qui peut être pratique dans la gestion des exceptions.
Exemple :
if (x == null) throw new ArgumentNullException(nameof(x));
WriteLine(nameof(personne.Addresse.CodePostal)); // affiche "CodePostal"
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 73
7 Délégués et Événements
7.1 Définition d'un délégué
Un délégué est un type (référence) qui permet de stocker des références à des fonctions. Il est
utilisé pour encapsuler une méthode d'une signature spécifique et la passer en paramètre. Il est
semblable à un pointeur de fonction en C++, sauf qu'il est de type sécurisé.
Le délégué délègue la méthode associée pour réaliser son travail.
Les délégués sont utiles pour la gestion des événements. Ils sont déclarés de manière similaire aux
fonctions :
• Mot-clé delegate,
• Sans corps de fonction,
• Un type de retour et une liste de paramètres.
On peut déclarer une variable avec le type délégué. Cette variable sera initialisée comme une
référence à toute fonction qui a le même type de retour et la même liste de paramètres que le
délégué. On peut alors appeler cette fonction en utilisant la variable de type délégué comme s'il
s'agissait d'une fonction.
Les avantages de l’utilisation des délégués sont alors :
• La possibilité de passer une variable de type délégué à une fonction comme paramètre,
• la fonction peut utiliser le délégué pour appeler une fonction, quelle qu’elle soit, et sans la
connaître avant l'exécution.
Le mot-clé delegate offre la possibilité de créer des classes particulières, appelées
"délégations", dont les instances sont nommées "délégués".
7.2 Déclaration des délégués
Syntaxe : [modifiers] delegate result identifier ([parameters])
où:
modifiers : est une combinaison valide de modificateurs d’accès plus le modificateur new.
Result : est le type du délégué qui est le même que celui de la méthode encapsulée.
Identifier : est le nom du délégué.
Parameters : est une liste optionnelle de paramètres.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 74
Exemple:
delegate void MonDelegue(object o1, object o2);
Ce délégué peut encapsuler des méthodes avec la même signature :
static void MaMethode(object o1, object o2) { ... }
7.3 Création du délégué
La création se fait selon les étapes suivantes :
1. Déclarer le délégué (dans un namespace ou une classe). Par exemple:
delegate void MonDelegue (object o1, object o2);
2. Déclarer la méthode qui lui sera associée. Exemple:
public static void MaMethode(object id, object nom){…}
Noter que les types de la valeur de retour et des paramètres sont identiques.
3. Créer un objet délégué :
MonDelegue delegObj = new MonDelegue(MaMethode);
Noter que le paramètre du délégué est le nom de la méthode encapsulée.
On peut aussi créer un objet délégué sans utiliser new:
MonDelegue delegObj = MaMethode;
7.4 Invocation du délégué
On utilise les mêmes paramètres utilisés pour appeler la méthode associée. Exemple:
delegObj(119, "Jane Doe");
Ou, à partir d’une méthode :
public static void AppelDelegue (MonDelegue meth)
{
meth(119, "Jane Doe");
}
On peut aussi utiliser la méthode .NET Invoke :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 75
delegObj.Invoke(119, "Jane Doe");
Exemple
// Déclarer un délégué:
delegate void MonDelegue(int n, string s);
class MainClass
{
static void Main()
{
// Instancier la classe:
MaClasse obj = new MaClasse();
// Instancier le delegué:
MonDelegue d = new MonDelegue(obj.MaMethode);
// Invoquer le delegue:
obj.AppelDelegue(d);
}
}
class MaClasse
{
// Une méthode pour invoquer le delegué:
public void AppelDelegue(MonDelegue meth)
{
meth(119, "Jane Doe");
}
// La méthode encapsulée :
public void MaMethode(int id, string nom)
{
Console.WriteLine("ID = {0}nNom = {1}", id, nom);
}
}
7.5 Associer un délégué à plusieurs méthodes
L’association entre un délégué et une méthode est réalisée dynamiquement lors de l’exécution. Le
délégué ne sait pas lors de la compilation, quelle méthode il va encapsuler. Ce qui importe, c’est la
signature et le type de retour de la méthode.
On peut donc associer le même délégué avec plus d’une méthode dans un programme.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 76
Exemple
public class Calc
{
// Declarer un délégué:
public delegate double Calcul(int x, int y, int z);
// Declarer les méthodes:
public static double Somme(int n1, int n2, int n3)
{
return n1 + n2 + n3;
}
public static double Moyenne(int n1, int n2, int n3)
{
return (n1 + n2 + n3) / 3;
}
public static void Main()
{
double resultat;
// Instancier le délégué, lui associer Moyenne :
Calcul monCalc = new Calcul(Moyenne);
// Invoquer le délégué:
resultat = monCalc(3, 6, 9);
Console.WriteLine("Moyenne: {0}", resultat);
// Instancier un autre objet et l'associate à Somme :
monCalc = new Calcul(Somme);
// Invoquer le délégué:
resultat = monCalc(3, 6, 9);
Console.WriteLine("Somme: {0}", resultat);
}
}
7.6 Ajouter ou supprimer des délégués
Les délégués peuvent être combinés en utilisant l’opérateur + pour créer un délégué composé.
L’invocation de ce délégué va provoquer l’invocation de ses constituants.
Le but de la composition est d’encapsuler plus d’une méthode dans le même délégué. Cette
opération est le multicasting.
On peut aussi supprimer un délégué d’une composition en utilisant le –.
On peut utiliser += et –=.
De manière similaire, on peut utiliser les méthodes .NET Combine et Remove qui sont membres
de la classe System.delegate.
Exemple
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 77
// Déclarer un délégué:
delegate void MonDelegue();
class MaClasse
{
public void MaMethode1()
{
Console.Write("MaMethode #1 ");
}
public void MaMethode2()
{
Console.Write("MaMethode #2 ");
}
}
class MainClass
{
static void Main()
{
// Instancier MaClasse:
MaClasse mc = new MaClasse();
// Déclarer un objet délégué et référencer MaMethode1:
MonDelegue d1 = new MonDelegue(mc.MaMethode1);
// Déclarer un objet délégué et référencer MaMethode2:
MonDelegue d2 = new MonDelegue(mc.MaMethode2);
// Déclarer le délégué d3 en additionnant d1 et d2.
// Cela invoquera MaMethode1 et MaMethode2:
MonDelegue d3 = d1 + d2;
// Déclarer le délégué d4 en retirant d1 de d3.
// Cela invoquera MaMethode2 uniquement:
MonDelegue d4 = d3 - d1;
Console.Write("Invoquer d1, référencer ");
d1();
Console.Write("nInvoquer d2, référencer ");
d2();
Console.Write("nInvoquer d3, référencer ");
d3();
Console.WriteLine("nInvoquer d4, référencer ");
d4();
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 78
7.7 Utiliser les méthodes .NET
// Combiner d1 et d2, pour former d3:
MonDelegue d3 = (MonDelegue) delegate.Combine(d1, d2);
// enlever d1 de d3, pour donner d4:
MonDelegue d4 = (MonDelegue) delegate.Remove(d3, d1);
Quand on utilise les méthodes .NET, il est nécessaire d’utiliser un ‘cast’ pour convertir le
résultat au type delegate.
7.8 Les événements
L'une des utilisations les plus importantes des délégués est la programmation d'événements,
notamment dans l'environnement Windows.
Un clic sur un bouton déclenche un événement pour lequel la réponse à cet événement peut
prendre plusieurs formes.
Le programmeur doit écrire la réponse appropriée à cet événement.
Un événement est reçu (réception) ou émis (émission).
Plusieurs types d'évènements sont possibles :
- Modifier du texte dans une zone de texte,
- Passer à un autre contrôle, …
La réception de l'événement dépend totalement de l'application en développement.
7.8.1 L'utilisation des événements
On commence par déclarer un délégué à utiliser comme gestionnaire (ou récepteur) :
delegate void RightButtonDown(object sender, EventArgs e);
On utilise ensuite le nom du délégué (RightButtonDown) comme type de l’évènement déclaré
avec le mot-clé event.
Par exemple, pour appeler l’évènement PressDown, on le définit comme suit:
event RightButtonDown PressDown;
Le mot clé event protège l'accès au délégué de la manière suivante :
• Il n'est plus possible d'utiliser l'affectation seule (opérateur =), il faut utiliser += ou -= ;
• L'ajout et le retrait sont réalisés de manière synchrone, c-à-d que chaque évènement
attend la fin du précédent pour s'exécuter. Si un évènement lance une exception, les
suivants ne seront pas exécutés;
• Il n'est pas possible d'appeler le delegate en dehors de la classe où l'event est
déclaré.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 79
Exemple:
class MonEventArgs : EventArgs
{
// Champs:
private string stock;
private int variation;
// Propriétés:
public string MonStock
{
get { return stock; }
}
public int MaVariation
{
get { return variation; }
}
// Constructeur:
public MonEventArgs(string s, int c)
{
stock = s;
variation = c;
}
}
class Emetteur
{
public delegate void MonGestionnaire(object source, MonEventArgs e);
public event MonGestionnaire Changement;
// Mettre à jour le stock
public void MettreAJour(string s, int c)
{
MonEventArgs e = new MonEventArgs(s, c);
if (Changement != null)
Changement(this, e);
}
}
// Classe qui reçoit l'évènement
class Recepteur
{
public Recepteur(Emetteur s)
{
// Ajouter l’évènement:
s.Changement += new Emetteur.MonGestionnaire(OnStockChange);
}
void OnStockChange(object source, MonEventArgs e)
{
string plusOuMoins;
if (e.MaVariation > 0)
plusOuMoins = "moins";
else plusOuMoins = "plus";
int ch = Math.Abs(e.MaVariation);
Console.WriteLine("{0} {1} {2}", e.MonStock, plusOuMoins, ch);
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 80
// Classe principale
class Program
{
public static void Main()
{
Emetteur s = new Emetteur();
Recepteur r = new Recepteur(s);
// Afficher les résultats:
Console.WriteLine("Ventes 2015:");
s.MettreAJour("tIntroduction à C#:", -20);
s.MettreAJour("tLivres C++:", 11);
s.MettreAJour("tLivres VB .NET:", -15);
s.MettreAJour("tLivres de Science Fiction:", 120);
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 81
8 Les Interfaces
Une interface permet de déclarer le contenu de la classe qui l’implémente. C’est un contrat qui
décrit le comportement de la classe qui implémente l’interface.
Si l’interface contient le nom d’une méthode, la classe qui l’implémente est obligée de contenir
l’implémentation de cette méthode.
8.1 Déclaration de l’interface
interface IMonInterface
{
// membres de l’interface
}
La déclaration peut être modifiée par une combinaison valide de modificateurs d’accès ou par le
mot-clé new. Elle peut aussi être précédée par des attributs.
Les membres d’une interface peuvent être:
• Des Méthodes
• Des Propriétés
• Des Indexeurs
• Des Événements
Cependant, l’interface ne peut pas contenir de champs. Les membres de l’interface sont publics
par défaut et on ne peut pas utiliser de modificateurs d’accès sur les membres.
8.2 Membres
Les membres d’une interface sont des signatures de méthodes, des propriétés, des indexeurs, ou
des évènements. Par exemple:
interface ICompteur
{
void Compter(int i);
int SetCompteur();
}
Une interface peut elle-même implémenter une ou plusieurs interfaces, comme dans l'exemple :
interface IMonInterface: Interface1, Interface2
{
// membres de l’interface
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 82
Dans cet exemple, IMonInterface implémente Interface1 et Interface2.
8.3 Implémentation de l’interface
L'interface peut être implémentée par une classe ou une structure comme le montre cet exemple :
class MaClasse:IMonInterface
{
// implémentation de la classe
}
Par cette déclaration, la classe MaClasse est tenue de mettre en œuvre tous les membres de
l’interface IMonInterface.
Une classe peut implémenter plus d'une interface:
Une classe peut également implémenter une autre classe en plus des interfaces:
class MaClasse: MaBaseClasse, IMonInterface1, IMonInterface2
{
// implémentation de la classe
}
Exemple
interface IPoint
{
// Propriétés :
int MonX
{
get; set;
}
int MonY
{
get; set;
}
}
class Point : IPoint
{
// Champs:
private int x;
private int y;
// Constructeur:
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// implementation des propriétés :
public int MonX
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 83
{
get { return x; }
set { x = value; }
}
public int MonY
{
get { return y; }
set { y = value; }
}
public static void AfficherMonPoint(IPoint monPoint)
{
Console.WriteLine("({0},{1})", monPoint.MonX, monPoint.MonY);
}
}
class MaClasse
{
static void Main()
{
Point monPoint = new Point(12, 300);
Console.Write("Mon point est créé avec les coordonnées: ");
Point.AfficherMonPoint(monPoint);
}
}
8.4 Utiliser is pour tester les types
Usage :
expression is type
où:
type est une référence à un type
Expression est l’objet à tester
Le résultat est true ou false
Exemple
interface I1
{
}
interface I2
{
}
class Class1 : I1, I2
{
}
class MaClasse
{
static bool TesterType(object obj)
{
if (obj is I1 & obj is I2 & obj is Class1)
return true;
else
return false;
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 84
}
public static void Main()
{
Class1 c = new Class1();
Console.WriteLine("Le résultat du test est: {0}",
TesterType(c));
}
}
8.5 Utiliser as pour convertir
Convertir une expression à un type référence spécifié. Usage:
expression as type
où:
type est une référence à un type,
Expression est l’objet à convertir.
Retourne la valeur de l’expression si la conversion réussit, null sinon. Ceci est équivalent à
‘caster’ expression avec type sauf qu’elle ne lance pas d’exception si la conversion échoue.
Seules les références d’objets sont converties.
Exemple :
object o = "Chaîne de car dérive de la classe object" as object;
Exemple complet
public class MaClasse
{
static void TesterType(object o)
{
if (o as MaClasse != null)
Console.WriteLine("L'objet "{0}" est une classe.", o);
else if (o as string != null)
Console.WriteLine("L'objet "{0}" est un string.", o);
else
Console.WriteLine("L'objet "{0}" n'est pas un type référence.", o);
}
static void Main()
{
MaClasse mc = new MaClasse();
string monString = "Bonjour le monde!";
int monInt = 123;
TesterType(mc);
TesterType(monString);
TesterType(monInt);
}
8.6 Cacher les membres d’une classe de base
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 85
Soit la classe de base:
public class MaBaseClass
{
public int monInt;
public void MaMethode()
// MaMethode dans la classe de base
{ // ...}
}
Pour utiliser le même nom d’un membre dans une classe héritée, on utilise new
public class MaClasseDerivee: MaBaseClass
{
new public void MaMethode()
// MaMethode de la classe dérivée
{
// ...
Une méthode qui utilise le modificateur new, cache les propriétés et les champs qui ont le même
nom. Elle cache aussi les méthodes avec les mêmes signatures.
En général, déclarer un membre dans la classe héritée, cache tout membre de la classe de base qui
porte le même nom.
On ne peut pas utiliser new et override dans la même déclaration mais on peut utiliser new
et virtual dans une même déclaration.
Exemple :
class BaseClasse
{
public virtual void Methode1()
{
Console.WriteLine("Base - Méthode1");
}
public void Methode2()
{
Console.WriteLine("Base - Methode2");
}
}
class DeriveeClass : BaseClasse
{
public override void Methode1()
{
Console.WriteLine("Dérivée - Méthode1");
}
public new void Methode2() // Masque methode2 de la
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 86
{ // classe de base. Il faut ajouter new
Console.WriteLine("Dérivée - Méthode2");
}
}
class Program
{
static void Main(string[] args)
{
BaseClasse bc = new BaseClasse();
DeriveeClass dc = new DeriveeClass();
BaseClasse bcdc = new DeriveeClass();
bc.Methode1(); // Base - Méthode1
bc.Methode2(); // Base – Méthode2
dc.Methode1(); // Dérivée - Méthode1
dc.Methode2(); // Dérivée – Méthode2
bcdc.Methode1(); // Dérivée - Méthode1
bcdc.Methode2(); // Base – Méthode2
}
}
Le mot-clé new préserve la relation d’héritage. Les variables de type BaseClasse continuent à
accéder aux membres de BaseClasse.
Le mot-clé override permet à bcdc (de valeur de type DeriveeClasse) d’accéder à la
méthode Methode1 qui est définie dans DeriveeClasse.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 87
9 L’interface Graphique (WinForms)
9.1 Contrôles
La plupart des contrôles en .NET dérivent de la classe :
System.Windows.Forms.Control qui définit les fonctionnalités de base des contrôles.
Certaines classes sont elles-mêmes des classes de base pour d’autres contrôles.
Exemples : classes Label et TextBoxBase
1. Les Propriétés
Tous les contrôles ont un certain nombre de propriétés qui sont utilisées pour en manipuler le
comportement.
Exemples
• Anchor: qui spécifie comment se comporte le contrôle quand la fenêtre est
redimensionnée.
• BackColor, ForeColor : Couleur d’arrière plan et d’avant plan du contrôle.
• Bottom : distance à partir du haut de la fenêtre au bas du contrôle.
• Dock : colle le contrôle au bord de son conteneur.
• Enabled : à true, le contrôle peut recevoir des entrées de l’utilisateur.
• Height: Hauteur du contrôle.
• Name : nom du contrôle utilisé pour le référencer
• Parent: Le parent du contrôle.
• TabIndex: Numéro du contrôle.
• TabStop: Indique si le contrôle peut être accédé par la touche Tab.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 88
• Text: Texte associé avec le contrôle.
• Visible: Indique si le contrôle est visible lors de l’exécution.
• Width: Largeur du contrôle.
2.2.2.2. Les événements
Voici quelques événements générés par les contrôles :
• Click, DoubleClick: L’utilisateur clique sur le contrôle ou appuie sur Enter,
• DragDrop: Une opération ‘drag - and – drop’ est terminée et l’utilisateur
lâche le bouton de la souris.
• DragEnter: un objet tiré entre dans les limites du contrôle. (DragLeave,
DragOver).
• KeyDown: une touche est activée quand le contrôle a le focus. Se produit toujours
avant KeyPress et KeyUp.
• KeyPress: Une touche est activée quand le contrôle a le focus (après KeyDown et
avant KeyUp).
• KeyUp: Une touche est relâchée quand le contrôle a le focus (après KeyDown et
KeyPress).
• GotFocus, LostFocus: Un contrôle reçoit ou perd le focus.
• MouseDown: La souris est sur le contrôle et l’utilisateur appuie sur un bouton.
(différent de Click car il intervient avant que le bouton est relâché).
• MouseMove: En continu quand la souris traverse le contrôle.
• MouseUp: Le pointeur de la souris est sur un contrôle et un bouton est relâché.
• Validated: Un contrôle avec la propriété CausesValidation à true va
recevoir le focus. Intervient après que l’évènement validant se termine et indique que
la validation est achevée.
Il existe trois méthodes de base pour gérer un événement particulier.
• Double-cliquer sur un contrôle, ce qui amène au gestionnaire d'événement pour le
contrôle de l’événement par défaut (différent pour chaque contrôle).
• Si événement autre que celui par défaut:
- Utiliser la liste des événements dans la fenêtre Propriétés,
- Ajouter soi-même le code à associer à l'événement.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 89
9.2 Boutons
Voici un exemple simple d’utilisation des boutons:
Pour créer cet exemple il faut :
- Tirer 3 fois le contrôle Button de la boîte à outils de Visual Studio,
- Changer la propriété name de chaque bouton pour le renommer,
- A chaque bouton associer le code approprié (double cliquer sur un bouton pour
accéder à son code).
Voici, par exemple, le code associé au bouton English
private void buttonEnglish_Click(object sender, EventArgs e)
{
this.Text = “Do you speak English?”;
}
private void buttonOK_Click(object sender, EventArgs e)
{
Application.Exit();
}
9.3 Les étiquettes (Label)
Il existe deux contrôles d'étiquette qui se présentent sous deux formes distinctes:
- Label qui est l’étiquette standard, et
- LinkLabel qui est une étiquette semblable à la précédent mais qui se présente comme
un lien hypertexte.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 90
9.4 Boîte de texte
Une boîte de texte est utilisée pour entrer du texte ou un nombre. Il existe dans cette catégorie
deux contrôles de base :
- TextBox
- RichTextBox.
Les deux sont dérivés de la classe de base : TextBoxBase.
Exemple
Dans cet exemple :
- La propriété Scrollbars des contrôles txtOutput et txtAddress est mise à
Vertical.
- La propriété ReadOnly du contrôle txtOutput est à true.
- La propriété CausesValidation du bouton btnHelp est à false. Cela permet aux
utilisateurs de cliquer sur ce bouton sans avoir à se soucier d'entrer des données invalides.
Voici le code associé à chacun des boutons :
private void buttonOK_Click(object sender, EventArgs e)
{
// Pas de test des valeurs invalides
string output;
// Concatene le texte des 4 TextBox.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 91
output = “Nom: “ + this.textBoxName.Text + “rn”;
output += “Adresse: “ + this.textBoxAddress.Text + “rn”;
output += “Fonction: “ + this.textBoxOccupation.Text +
“rn”;
output += “Age: “ + this.textBoxAge.Text;
// Insère le nouveau texte.
this.textBoxOutput.Text = output;
}
private void buttonHelp_Click(object sender, EventArgs e)
{
string output;
output = “Nom = Votre nom rn”;
output += “Adresse = Votre adressern”;
output += “fonction = Seule valeur possible :
Programmeur’rn”;
output += “Age = Votre âge”;
// Insère le nouveau texte.
this.textBoxOutput.Text = output;
}
9.5 Les contrôles RadioButton et CheckBox
Ces contrôles permettent d’insérer des boutons radios ou des cases à cocher.
Exemple :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 92
Dans cet exemple :
- La propriété checked de la case à cocher checkBoxProgrammer est à true.
- La propriété Checked de radioButtonMale ou deradioButtonFemale est à
true.
9.6 Le contrôle RichTextBox
Ce contrôle est utilisé pour afficher et entrer du texte formaté (par exemple, gras, souligné et en
italique). Il utilise le format RTF (Rich Text Format).
Exemple :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 93
Voici le code associé aux boutons de cet exemple :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 94
9.7 Les contrôles ListBox et CheckedListBox
Les zones de liste sont utilisées pour afficher une liste de string à partir de laquelle un ou
plusieurs éléments peuvent être sélectionnés à la fois. Cette zone de liste permet aux utilisateurs
de faire une ou plusieurs sélections.
Le contrôle CheckedListBox fournit une liste, mais en plus du texte, il fournit une marque qui
permet de vérifier chaque élément dans la liste.
Exemple
Voici le code associé à cet exemple :
public Form1()
{
InitializeComponent();
// Ajouter un element à la CheckedListBox.
this.checkedListBoxPossibleValue.Items.Add(“Ten”);
}
private void buttonMove_Click(object sender, EventArgs e)
{
if(this.checkedListBoxPossibleValue.CheckedItems.Count>0)
{
this.listBoxSelected.Items.Clear();
foreach (string item in
this.checkedListBoxPossibleValue.CheckedItems)
{
this.listBoxSelected.Items.Add(item.ToString());
}
for (int
i=0;i<this.checkedListBoxPossibleValue.Items.Count; i++)
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 95
this.checkedListBoxPossibleValue.SetItemChecked(i,
false);
}
}
9.8 Menus
Visual Studio offre 2 types de contrôles pour créer facilement des menus déroulants:
- Pour créer un menu normal on utilise le contrôle MenuStrip
- Pour un menu contextuel on utilise le contrôle ContextMenuStrip .
Voilà le texte à saisir pour
créer le menu ci-contre
&New
&Open
-
&Save
Save &As
-
&Print
Print Preview
-
E&xit
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 96
10 Introduction à Windows Presentation Foundation
10.1 Introduction
WPF représente la nouvelle génération d’interfaces utilisateur de Microsoft. Il permet de créer des
applications graphiques riches. Il fait partie du framework .NET 3.0 et plus.
WPF combine les applications d’interfaces utilisateur, le graphisme 2D, le graphisme 3D, les
documents et le multimédia dans un même framework. C’est une UI plus rapide, évolutive et
indépendante de la résolution d’écran.
10.2 Principales caractéristiques de WPF
• Séparation de l’apparence et du comportement
WPF sépare l’apparence de l’interface de son comportement (code). L’apparence est généralement
spécifiée en Extensible Application Markup Language (XAML), le comportement est implémenté
en C# ou Visual Basic.
• Compositions riches
Les contrôles WPF sont extrêmement composables. N’importe quel type de contrôle peut être
défini comme le contenu d’un autre contrôle.
<Button>
<StackPanel Orientation="Horizontal">
<Image Source="speaker.png" Stretch="Uniform"/>
<TextBlock Text="Play Sound" />
</StackPanel>
</Button>
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 97
• Personnalisation extrême
Grâce à la stricte séparation de l’apparence du code, il est très facile de changer le look d’un
contrôle. Le concept de styles permet d’habiller les contrôles comme avec CSS en HTML. Les
gabarits (Templates) permettent d’en remplacer toute l’apparence.
Voilà un exemple de bouton standard puis personnalisé.
• Indépendance de la résolution
Les mesures dans WPF sont des unités logiques et non des pixels. Une unité logique est un 1/96
d'un pouce. Quand on augmente la résolution de l’écran, l'interface reste de la même taille - cela
devient juste plus précis.
WPF est construit sur un moteur de rendu vectoriel ce qui rend très facile de construire des
interfaces scalables.
10.3 Créer une application WPF simple
Ouvrir Visual Studio et choisir un projet du type "WPF Application».
La structure du projet ressemble à WinForms, sauf que le fichier Window1.designer.cs n’est
plus du code mais du XAML déclaré dans MainWindow.xaml
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 98
Ouvrez le fichier MainWindow.xaml dans le concepteur WPF et ajoutez un Bouton et une
TextBox.
Changez le texte du bouton. Double-cliquez sur le bouton et ajoutez-lui le code :
private void button1_Click(object sender, RoutedEventArgs e)
{
txtBonjour1.Text = "Bonjour WPF!";
}
Testez votre application.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 99
10.4 Contrôle TextBox
Activer la correction orthographique
TextBox et RichTextBox permettent la correction orthographique pour les langages : anglais,
espagnol, allemand et français. On l’active en mettant la propriété SpellCheck.IsEnabled à
true.
<TextBox SpellCheck.IsEnabled="True" Language="en-US" />
Valider l’entrée en utilisant les expressions régulières :
protected override void OnTextInput(TextCompositionEventArgs e)
{
string fullText = Text.Remove(SelectionStart, SelectionLength) +
e.Text;
if (_regex != null && !_regex.IsMatch(fullText))
{
e.Handled = true;
}
else
{
base.OnTextInput(e);
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 100
10.5 Contrôle Bouton Radio
Pour grouper des RadioButtons on met la propriété GroupName au même nom. Pour
préselectionner une option on met sa propriété IsChecked à True.
<StackPanel>
<RadioButton GroupName="Os" Content="Windows 7"
IsChecked="True"/>
<RadioButton GroupName="Os" Content="Windows 8.1" />
<RadioButton GroupName="Os" Content="Windows 10" />
<RadioButton GroupName="Office" Content="Microsoft Office 2010"
IsChecked="True"/>
<RadioButton GroupName="Office" Content="Microsoft Office
2013"/>
<RadioButton GroupName="Office" Content="Open Office"/>
</StackPanel>
Contrôle ListBox
Code XAML:
<ListBox Margin="20">
<ListBoxItem>New York</ListBoxItem>
<ListBoxItem>Los Angeles</ListBoxItem>
<ListBoxItem>Paris</ListBoxItem>
<ListBoxItem>Zürich</ListBoxItem>
</ListBox>
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 101
10.6 Ajouter supprimer dynamiquement un élément
•••• Ajouter une TextBox et un bouton ‘Ajouter’. Associer au bouton le code :
private void button1_Click(object sender, RoutedEventArgs e)
{
listBox1.Items.Add(textBox1.Text);
}
•••• Ajoutez un bouton ‘Supprimer’ et lui associer le code
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
listBox1.Items.RemoveAt
(listBox1.Items.IndexOf(listBox1.SelectedItem));
}
10.7 Créer un Menu
<Menu IsMainMenu="True">
<MenuItem Header="_File" />
<MenuItem Header="_Edit" />
<MenuItem Header="_View" />
<MenuItem Header="_Window" />
<MenuItem Header="_Help" />
</Menu>
•••• Les MenuItem
Le contenu de Header est l’affichage du menu. Les Items sont les sous-menus. La propriété
Icon permet de rajouter un second contenu (une image) à la gauche de l’affichage. On peut
definir un raccourci clavier en ajoutant un underscore devant le caractère.
<MenuItem Header="_Edit">
<MenuItem Header="_Cut" Command="Cut">
<MenuItem.Icon>
<Image Source="Images/cut.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Copy" Command="Copy">
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 102
<MenuItem.Icon>
<Image Source="Images/copy.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Paste" Command="Paste">
<MenuItem.Icon>
<Image Source="Images/paste.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
•••• Menus Contextuels en WPF
Les Menus Contextuels peuvent être definis sur n’importe quel contrôle WPF en associant sa
propriété ContextMenu à une instance de ContextMenu. Les éléments du menu contextual sont
des MenuItems classiques.
<RichTextBox>
<RichTextBox.ContextMenu>
<ContextMenu>
<MenuItem Command="Cut">
<MenuItem.Icon>
<Image Source="Images/cut.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="Copy">
<MenuItem.Icon>
<Image Source="Images/copy.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="Paste">
<MenuItem.Icon>
<Image Source="Images/paste.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</RichTextBox.ContextMenu>
</RichTextBox>
Ouvrir un menu contextuel à partir du code
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 103
Exemple:
private void OpenContextMenu(FrameworkElement element)
{
if( element.ContextMenu != null )
{
element.ContextMenu.PlacementTarget = element;
element.ContextMenu.IsOpen = true;
}
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 104
11 Collections et itérateurs - Génériques
Il existe diverses classes pour stocker des collections d'éléments en plus des tableaux. Ces
collections ont été introduites pour pallier aux différents inconvénients des tableaux (statiques de
taille fixe).
Ces collections sont soit sous la forme non-générique, c-à-d dédiées à un type particulier, ou
génériques.
Elles sont définies dans les espaces de noms :
System.Collections et System.Collections.Generic
Dans la suite, et comme illustration des collections non génériques, nous présentons la collection
ArrayList et deux collections génériques fréquemment utilisées : la liste et le dictionnaire.
11.1 Exemples de collections
Voici quelques exemples de collections qui ne seront (malheureusement) pas toutes présentées
dans ce support de cours :
 La collection Stack : Classe LIFO qui représente une PILE (dernier entré premier
servi).
 La collection Queue : Classe FIFO qui représente une FILE (premier entré premier
servi).
 La collection ArrayList : qui représente un tableau dynamique non trié
 La collection SortedList : similaire à ArrayList mais trié sur une clé
 La collection Hashtable : Collection d'entrées clé/valeur. Les entrées sont triées selon
le code de hachage de la clé.
 La collection Linked List : qui représente une liste linéaire doublement chaînée
11.2 La classe non générique ArrayList
ArrayList est capable de stocker des références sur des objets quelconques. Un objet
ArrayList ressemble à ceci :
Les éléments 0, 1 et i de la liste pointent sur des objets de types différents. Bien entendu, Il faut
qu'un objet soit d'abord créé avant d'ajouter sa référence à la liste ArrayList.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 105
Bien qu'un ArrayList stocke des références d'objet, il est possible d'y stocker des nombres par
utilisation du Boxing.
Exemple :
ArrayList liste=new ArrayList();
liste.Add(4);
// récupérer le nombre : Unboxing
int i = (int)liste[0];
Les méthodes disponibles sont:
add, insert, clone, contains, getEnumerator, reverse, sort, …
Exemple d’ArrayList
static void Main(string[] args)
{
// Créer une ArrayList:
ArrayList monArrayList = new ArrayList();
// Afficher la capacité initiale
Console.WriteLine("La capacité initiale est : {0}",
monArrayList.Capacity);
// Initialiser la liste avec des éléments:
monArrayList.Add("SNL");
monArrayList.Add("Mad TV");
monArrayList.Add("Seinfeld");
monArrayList.Add("Everybody Loves Raymond");
monArrayList.Add("Married with Children");
// Afficher le nombre d'éléments
Console.WriteLine("The number of items: {0}",
monArrayList.Count);
// Afficher la nouvelle capacité:
Console.WriteLine("La capacité est maintenant : {0}",
monArrayList.Capacity);
// Afficher les éléments de la liste
Console.WriteLine("nLe contenu de l'ArrayList: ");
DisplayIt(monArrayList);
// Trier et afficher la liste
monArrayList.Sort();
Console.WriteLine("nLe contenu de l'ArrayList triée: ");
DisplayIt(monArrayList);
}
public static void DisplayIt(ArrayList maListe)
{
foreach (object item in maListe)
Console.WriteLine("{0}", item);
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 106
11.3 Utilisation des énumérateurs
Les énumérateurs permettent de parcourir une collection. Ils sont uniquement utilisés pour lire
des données et ne peuvent pas modifier la collection. On les crée en implémentant les interfaces
IEnumerable et IEnumerator :
IEnumerator contient 2 méthodes abstraites, MoveNext et Reset, et une propriété
Current.
object Current {get;}
bool MoveNext()
void Reset()
Ces méthodes permettent de parcourir les collections en utilisant une boucle foreach. Ce qui
est recommandé car cela cache la complexité des énumérateurs.
11.3.1 IEnumerator
L’implémentation de cette interface permet de lire la collection. Pour cela :
– Appeler MoveNext pour aller sur le premier élément de la collection,
– Puis utiliser Current pour lire les éléments.
– Chaque lecture suivante doit être précédée de MoveNext.
Si l’énumérateur est avant le premier élément ou après le dernier, MoveNext retourne false
et la valeur de Current devient indéfinie.
Exemple
// Declarer la collection:
public class MaCollection : IEnumerable
{
string[] items;
public MaCollection()
{
items = new string[4] { "Ceci", "est", "ma", "collection." };
}
// Implementer la méthode GetEnumerator() :
IEnumerator IEnumerable.GetEnumerator()
{
return new MonEnumerator(this);
}
// Implementer les membres de IEnumerator:
public class MonEnumerator : IEnumerator
{
int pointeur;
MaCollection maColl;
public MonEnumerator(MaCollection c)
{
maColl = c;
pointeur = -1;
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 107
// Implementer Reset:
public void Reset()
{
pointeur = -1;
}
// Implementer MoveNext:
public bool MoveNext()
{
pointeur++;
if (pointeur > maColl.items.Length - 1)
return false;
return true;
}
// Implementer la propriété Current dans IEnumerator:
object IEnumerator.Current
{
get
{
return (maColl.items[pointeur]);
}
}
}
}
class maClass
{
public static void Main(string[] args)
{
MaCollection maColl = new MaCollection();
// Display the collection:
foreach (string item in maColl)
{
Console.Write(item + " ");
}
Console.WriteLine();
}
}
Autre exemple : nouvelle version de l’exemple précédent qui utilise un énumérateur basé sur
l’interface IDictionaryEnumerator.
public class LDClasse
{
public static void Main(string[] args)
{
// Créer un objet ListDictionary vide
ListDictionary monLD = new ListDictionary();
// Initialiser la collection ListDictionary .
monLD.Add("Learn Pascal", "$39.95");
monLD.Add("Learn Pascal in Three Days", "$19.95");
monLD.Add("Learn C in Three Days", "$19.95");
monLD.Add("Learn J#", "$35.95");
monLD.Add("Learn C#", "$39.95");
// Afficher le contenu de la collection:
DisplayIt(monLD);
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 108
// Afficher le contenu en utilisant un énumerateur:
public static void DisplayIt(IDictionary maLD)
{
IDictionaryEnumerator monEnumerateur = maLD.GetEnumerator();
string s = "tttt";
Console.WriteLine("Livre{0}Prixn", s);
while (monEnumerateur.MoveNext())
Console.WriteLine("{0,-32}{1}", monEnumerateur.Key,
monEnumerateur.Value);
}
}
11.4 Itérateurs
L'application de l’interface IEnumerator peut être difficile, surtout avec des énumérations
complexes. C # 2005 a introduit les itérateurs pour résoudre le problème de cette
complexité.
Un itérateur est utilisé pour parcourir une collection et retourner une séquence de valeurs
du même type. L'épine dorsale de l’itérateur est le mot-clé yield qui spécifie la valeur retournée.
Pour créer un itérateur il faut implémenter la méthode GetEnumerator de l'interface
IEnumerable:
class MaClasse
{
public string[] item = {"One", "Two", Three"};
public IEnumerator GetEnumerator()
{
for (int i = 0; i < item.Length; i++)
yield return item[i];
}
}
La présence de la méthode GetEnumerator rend la classe énumérable ce qui permet d’utiliser
la boucle foreach :
MaClasse mc = new MaClasse();
foreach (string item in mc)
{
Console.WriteLine(item);
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 109
11.4.1 L’instruction yield
yield return expression;
Cette instruction est utilisée pour itérer une collection. Elle est utilisée pour évaluer et retourner
expression, qui est la valeur de l'objet itérateur. Cette instruction retourne la propriété
Current de l’élément.
L’instruction
yield break;
est utilisée pour terminer l'énumération.
Il est possible d'utiliser plus d'une déclaration yield return dans un même itérateur pour
retourner plusieurs valeurs comme dans l’exemple suivant :
public class MaClasse
{
public IEnumerable MonIterator()
{
yield return "Bonjour!";
yield return "Je suis votre itérateur.";
yield return "Je peux retourner";
yield return "autant d'éléments que nécessaire.";
}
public static void Main()
{
MaClasse mc = new MaClasse();
foreach (string item in mc.MonIterator())
Console.Write(item + " ");
}
}
11.5 Les collections génériques
C’est une fonctionnalité permettant au programmeur de concevoir des classes ou des membres
de fonction tout en reportant la définition du type à l’instanciation de la classe.
Sans génériques, si on a besoin d'une pile d'entiers et d’une pile de chaînes de caractères, on doit
créer une collection pour chaque type.
Avec les génériques, on peut créer une collection générique utile pour tous les types, et reporter
la spécification du type réel au moment de la création des objets.
On utilise l'espace de noms System.Collections.Generic.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 110
11.5.1 Exemples de classes génériques
List<T>
Stack<T>
Dictionary<TKey, TValue>
LinkedList<T>
Exemple d’utilisation de la collection générique Stack :
Stack<double> maPile = new Stack<double>();
Stack<int> maPile = new Stack<int>();
Stack<string> maPile = new Stack<string>();
On détermine le type lors de l’instanciation de la classe Stack.
La syntaxe de la classe générique Stack est :
public class Stack<T> { }
La lettre T, est appelée type du paramètre, est remplacée lors de l’instanciation par type argument, qui
est n’importe quel type (int, double, …). On peut créer des types, des méthodes, des
propriétés, des délégués, et des interfaces génériques.
11.5.2 La classe générique List<T>
La classe System.Collections.Generic.List<T> permet d'implémenter des collections
d'objets de type T dont la taille varie au cours de l'exécution du programme. Un objet de type
List<T> se manipule presque comme un tableau: l'élément i d'une liste l est noté l[i].
List<T> implémente les interfaces génériques IList<T>, ICollection<T> et
IEnumerable<T> et les interfaces non-génériques IList, ICollection et
IEnumerable.
Il est à noter que ArrayList est fonctionnellement équivalente à List<Object>.
Si une liste est entièrement composée de types int, la déclarer comme List<int> améliore les
performances: les nombres de type int sont stockés dans la liste elle-même et non dans des
types Object extérieurs à la liste. Il n’est donc pas nécessaire de recourir au
Boxing/Unboxing.
Pour un objet List<T> où T est une classe, la liste stocke là encore les références des objets de
type T.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 111
11.5.2.1Propriétés de List<T>
– public int Count {get;} // qui donne le nombre d'éléments de la liste
– public int Capacity {get;} // qui donne le nombre d'éléments que la liste peut
contenir avant d'être redimensionnée. Le redimensionnement se fait automatiquement.
11.5.2.2Méthodes des listes génériques
– public void Add(T item) : ajoute item à la liste.
– public int BinarySearch<T>(T item) : retourne la position de item dans la liste
s'il s'y trouve sinon un nombre <0.
– public int BinarySearch<T>(T item, IComparer<T> comparateur) : idem
mais le 2ième
paramètre permet de comparer deux éléments de la liste. Utilise l'interface
IComparer<T>.
– public void Clear() : supprime tous les éléments de la liste.
– public bool Contains(T item) : retourne True si item est dans la liste.
– public void CopyTo(T[] tableau) : copie les éléments de la liste dans tableau.
– public int IndexOf(T item): retourne la position de item dans tableau ou -1 si
non trouvé.
– public void Insert(T item, int index) : insère item à la position index.
– public bool Remove(T item): supprime item de la liste. La méthode retourne
True si l'opération réussit, False sinon.
– public void RemoveAt(int index) : supprime l'élément n° index de la liste.
– public void Sort(IComparer<T> comparateur) : trie la liste selon un ordre
défini par comparateur.
– public void Sort() : trie la liste selon l'ordre défini par le type des éléments de la
liste.
– public T[] ToArray() : retourne les éléments de la liste sous forme de tableau
Exemple
static void Main(string[] args)
{
// Déclarer la liste:
List<string> maListe = new List<string>();
// Construire la liste:
maListe.Add("Dylan");
maListe.Add("Isabella");
maListe.Add("Eve");
maListe.Add("Angelina");
// Afficher les éléments:
DisplayIt(maListe);
// Ajouter un nouvel élément:
maListe.Insert(3, "Bill");
Console.WriteLine("Adding Bill...");
// Afficher les éléments:
DisplayIt(maListe);
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 112
// Rechercher l'élément "Bill" dans la liste:
bool test = maListe.Contains("Bill");
Console.WriteLine("Est-ce que "Bill" est dans la liste? {0}", test);
// Enlever "Bill" et le rechercher à nouveau:
maListe.Remove("Bill");
Console.WriteLine("Enlever Bill...");
test = maListe.Contains("Bill");
Console.WriteLine("Est-ce que "Bill" est dans la liste? {0}", test);
Console.WriteLine();
// Afficher les éléments:
DisplayIt(maListe);
// Afficher l'élément #2:
Console.WriteLine("Élément numéro 2: {0}", maListe[2]);
}
// Afficher la liste:
static void DisplayIt(List<string> maL)
{
foreach (string nom in maL)
{
Console.WriteLine(nom);
}
Console.WriteLine();
}
11.5.3 La classe Dictionary<TKey,TValue>
Cette classe permet d'implémenter un dictionnaire. On peut voir un dictionnaire comme un
tableau à deux colonnes :
Les clés sont de type Tkey et les valeurs de type TValue. Les clés sont uniques. La valeur associée
à la clé C d'un dictionnaire D est obtenue par la notation D[C]. Cette valeur est en lecture et
écriture.
Exemple:
TValue v=...;
TKey c=...;
Dictionary<TKey,TValue> D = new Dictionary<TKey,TValue>();
D[c]=v;
v=D[c];
Si la clé c n'existe pas dans le dictionnaire D, la notation D[c] lance une exception.
La classe Dictionary implémente les interfaces génériques :
 IDictionary<TKey, TValue>
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 113
 ICollection<KeyValuePair<TKey, TValue>>
 IEnumerable<KeyValuePair<TKey, TValue>>
Et les interfaces non-génériques :
 IDictionary
 ICollection
 IEnumerable
 ISerializable
 IDeserializationCallback
11.5.3.1 Constructeurs et Propriétés
Constructeurs
– public Dictionary<TKey,TValue>() : est un constructeur sans paramètres qui
construit un dictionnaire vide.
– public Dictionary(int capacity)
– public Dictionary(IDictionary<Tkey,TValue> dictionary)
Propriétés
– public int Count {get;} : nombre d'entrées (clé, valeur) dans le dictionnaire
– public Dictionary<TKey,TValue>.KeyCollection Keys {get;} :qui
retourne la collection des clés du dictionnaire.
– public Dictionary<TKey,TValue>.ValueCollection Values {get;}:
retourne la collection des valeurs du dictionnaire.
Méthodes
– public void Add(TKey key, TValue value) : ajoute le couple (key, value) au
dictionnaire.
– public void Clear() : supprime tous les couples du dictionnaire.
– public bool ContainsKey (TKey key) : retourne True si key est une clé du
dictionnaire, False sinon.
– public bool ContainsValue (TValue value) : retourne True si value est une
valeur du dictionnaire, False sinon.
– public void CopyTo(T[] tableau) : méthode qui copie les éléments de la liste
dans tableau.
– public bool Remove(TKey key) : méthode qui supprime du dictionnaire le couple
de clé key. Cette méthode retourne True si l'opération réussit, False sinon.
– public bool TryGetValue(TKey key,out TValue value): retourne dans
value, la valeur associée à la clé key si cette dernière existe, sinon rend la valeur par
défaut du type TValue (0 pour les nombres, false pour les booléens, null pour les
références d'objet)
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 114
Exemple
public static void Main()
{
// Créer une collection Dictionary vide
Dictionary<string, double> monDictionnaire = new Dictionary<string,
double>();
// Ajouetr des éléments au dictionnaire
// On assume que les clés sont les fruits et les valeurs les prix.
// Les prix peuvent être dupliqués.
monDictionnaire.Add("Pommes", 0.30);
monDictionnaire.Add("Oranges", 0.50);
monDictionnaire.Add("Cerises", 0.44);
monDictionnaire.Add("Pêches", 0.50);
// Afficher le éléments en utilisant les paires Clé/Valeur :
foreach (KeyValuePair<string, double> mD in monDictionnaire)
{
Console.WriteLine("{0,-20}{1:C}", mD.Key, mD.Value);
}
// Chercher les cerises et afficher le prix:
ChercherElement(monDictionnaire, "Cerises");
// Chercher les "Oranges," et afficher le prix:
ChercherElement(monDictionnaire, "Oranges");
// Enlever les "Oranges":
monDictionnaire.Remove("Oranges");
Console.WriteLine("Oranges enlevées...");
// Chercher les "Oranges," et afficher le prix:
ChercherElement(monDictionnaire, "Oranges");
}
// Une méthode pour rechercher une clé spécifique dans le Dictionnaire:
static void ChercherElement(Dictionary<string, double>
monDictionnaire,
string s)
{
if (monDictionnaire.ContainsKey(s))
Console.WriteLine("{0} sont en magasin. Le prix est {1:C}.",
s, monDictionnaire[s]);
else
Console.WriteLine("{0} ne sont pas en magasin. SVP revenez plus
tard.", s);
}
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 115
12 ADO.NET
12.1. SQL Server et Visual Studio
La version Express de Visual Studio est livrée avec SQL Server Compact 3.5. Cet SGBD léger ne
sait gérer qu'un utilisateur à la fois, mais il suffisant pour introduire la programmation avec les
bases de données.
Nous présentons ci-après quelques concepts nécessaires à l’exploitation d’une base de données
dans Visual Studio.
1.1 Configurer la Base de Données
Pour utiliser une BD existante on suit les étapes ci-après:
- Afficher l’explorateur de serveurs,
- Cliquer avec le bouton droit sur le nœud Connections de données,
- Entrer localhost comme nom de serveur,
- Cliquer sur « Tester la Connexion »
- Choisir la DB (Sélectionner ou Entrer un nom de base de données).
Pour créer une nouvelle BD, on fait:
- Afficher l’explorateur de serveurs,
- Créer une nouvelle base de données SQL Server
11.1.2 Créer une table
Pour créer une table :
- Ouvrir l’onglet de la BD et
- faire un clic droit sur tables puis
- Ajouter table
- Rentrer les colonnes de la table
- Dans le script en bas de la fenêtre, choisir le nom de la table puis faire ‘Mettre à jour’.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 116
1.2 SQL : Rappels
- Instruction SELECT
Permet de réaliser une sélection de lignes dans une ou plusieurs tables. Sa syntaxe est la suivante :
SELECT [colonnes] FROM [tables] WHERE [condition] ORDER BY
[expression ASC | DESC]
Exemples (sur la BD PUBS de Microsoft):
•••• SELECT * FROM Authors
•••• SELECT lname, fname FROM Authors WHERE State='CA' ORDER BY
lname ASC
•••• SELECT TOP 100 * FROM Sales ORDER BY ord_date DESC
•••• SELECT * FROM Sales WHERE ord_date < '2000/01/01' AND ord_date
> '1987/01/01‘
•••• SELECT * FROM Stores WHERE stor_name LIKE '%book%‘
•••• SELECT COUNT(*) FROM Authors
•••• SELECT SUM(qty) FROM Sales
- Instruction UPDATE:
L’instruction UPDATE sélectionne tous les enregistrements qui correspondent à une expression
et les modifie selon l’expression spécifiée dans le UPDATE. Sa syntaxe est :
UPDATE [table] SET [expression] WHERE [condition]
Exemples:
- UPDATE Authors SET phone='408 496-2222' WHERE id='172-32-1176‘
- UPDATE Authors SET lname='Whiteson', fname='John‘ WHERE
lname='White' AND fname='Johnson‘
- UPDATE Titles SET price=price+1 WHERE pubdate >= '1991/01/01'
AND pubdate < '1992/01/01'
- Instruction INSERT
L’instruction INSERT permet d’ajouter une ligne à une table. La syntaxe est :
INSERT INTO [table] ([liste_colonnes]) VALUES
([liste_valeurs])
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 117
Exemple
INSERT INTO Authors (id, lname, fname, zip, contract) VALUES
('998-72-3566', 'Khan', 'John', 84152, 0)
- Instruction DELETE:
L’instruction DELETE permet de supprimer des lignes dans une table. Sa syntaxe est :
DELETE FROM [table] WHERE [condition]
Exemple:
DELETE FROM Authors WHERE id='172-32-1176'
- Les fonctions d’agrégation sont données par le tableau suivant :
12.2. Les Bases de ADO.NET
ADO.NET est un petit ensemble de classes de base qui sont de 2 types:
- Les classes pour contenir et gérer les données (DataSet, DataTable, DataRow et
DataRelation). Ces classes sont génériques et toutes les données sont stockées dans
un DataSet (voir infra).
- Les classes pour se connecter à une source de données spécifique (Connection,
Command et DataReader). Il existe plusieurs types de fournisseurs de données
ADO.NET (data provider ) qui sont optimisés pour améliorer l'interaction avec la
source de données.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 118
Exemples de fournisseurs:
• SQL Server provider pour l’accès à SQL Server
• OLE DB provider pour l’accès à n’importe quelle source qui a un driver OLE DB
(Object Linking and Embedding, Database)
• Oracle provider: accès à une BD Oracle (version 8i ou plus)
• ODBC provider: accès à n’importe quelle source qui a un driver ODBC (Open
Database Connectivity).
Les connecteurs ODBC présentent une interface standard aux applications qui les utilisent et qui
peuvent ainsi dialoguer avec tout SGBD ayant un connecteur ODBC. Les performances des
connecteurs ODBC sont moins bonnes que celles des connecteurs "propriétaires" qui savent
exploiter toutes les caractéristiques d'un SGBD particulier. En contre-partie, on obtient une
grande souplesse de l'application.
Les pilotes OLE DB sont similaires aux pilotes ODBC. Alors que les pilotes ODBC permettent
l'accès à des bases de données, les sources de données pour les pilotes OLE DB sont plus variées:
bases de données, messageries, annuaires, ...
1. Espaces de noms ADO pour Microsoft SQL Server
L’espace de noms System.Data contient des classes ADO.NET fondamentales qui proposent les
fonctionnalités de base.
Exemples: DataSet et DataRelation, qui permettent de manipuler des données
relationnelles. Ces classes sont totalement indépendantes de tout type spécifique de base de
données ou de la façon de s’y connecter.
L’espace de noms System.Data.SqlClient contient les classes à utiliser pour la connexion à
une base de données Microsoft SQL Server (version 7.0 ou ultérieure) et d'exécuter des
commandes.
Les classes ADO.NET Data Provider sont les suivantes :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 119
Nous allons détailler leur utilisation dans la suite de ce chapitre.
2. Accès direct aux données
Pour obtenir simplement des informations avec accès simples, on doit suivre ces étapes:
• Créer les objets Connection, Command et DataReader,
• Utiliser le DataReader pour récupérer l’information de la base de données, et l'afficher
dans un contrôle,
• Fermer la connexion,
• Envoyer la page à l'utilisateur. À ce stade, les informations que l’utilisateur voit et
l'information dans la base de données n'ont plus aucun lien, et tous les objets ADO.NET
ont été détruits.
Pour ajouter ou mettre à jour l'information on suit ces étapes:
• Créer les objets connection et command,
• Exécuter la commande (avec l’instruction SQL appropriée).
1. Créer une Connexion
Avant de récupérer ou mettre à jour les données, il faut établir une connexion à la source de
données. En général, le nombre de connexions est limité (licence ou charge du serveur). Il faut
donc garder une connexion ouverte pour une durée aussi courte que possible, écrire le code dans
un bloc try/catch et s’assurer de fermer la connexion.
Pour créer un objet Connection, il faut spécifier une valeur pour sa propriété
ConnectionString qui définit tous les détails pour trouver la source de données, se connecter
et choisir une base de données initiale.
Exemple:
SqlConnection maConnection = new SqlConnection();
maConnection.ConnectionString = "Data Source=localhost;" +
"Initial Catalog=Pubs;Integrated Security=SSPI";
Dans la ConnectionString :
• Data source: indique le nom du serveur sur lequel la source de données se trouve. Si
le serveur est sur le même ordinateur qui héberge le site ASP.NET, localhost est
suffisant.
• Initial catalog: nom de la base à accéder. "initial" signifie qu’on pourra la modifier
par la suite en utilisant la méthode Connection.ChangeDatabase().
• Integrated security: indique que l’on se connecte à SQL Server en utilisant le
compte utilisateur Windows qui exécute le code de page web, à condition de fournir une
valeur de SSPI (Security Support Provider Interface).
• Alternativement, on peut fournir un nom d'utilisateur et mot de passe définis dans
la base de données pour l'authentification SQL Server.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 120
• ConnectionTimeout: durée d'attente, en secondes, avant de
générer une erreur si on ne peut pas établir une connexion (défaut 15 sec; 0: pas de
limite)
2. Comment stocker la Connection String?
Généralement, tout le code de l’application utilise la même chaîne de connexion pour utiliser la
BD. On peut donc stocker une chaîne de connexion dans une variable membre de classe ou,
mieux, un fichier de configuration.
On peut aussi créer un objet de connexion et fournir la chaîne de connexion en une seule étape
en utilisant un constructeur dédié :
SqlConnection maConnection = new SqlConnection(connectionString);
// maConnection.ConnectionString is now set to connectionString.
3. Se Connecter
Ouvrir la connexion se fait à l’aide de l’instruction
maConnection.Open();
L’instruction
maConnection.Close();
Ferme la connexion. Une autre approche est possible qui utilise using:
4. La Commande Select
Pour récupérer les données il faut :
• Une instruction SQL qui sélectionne l’information souhaitée,
• Un objet Command qui éxécute l’instruction SQL ,
• Un objet DataReader ou DataSet pour accéder aux enregistrements.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 121
Exemple:
SqlCommand maCommand = maConnection.CreateCommand();
maCommand.CommandText = "SELECT CustomerID, CompanyName from
Customers";
Ou avec un constructeur :
SqlCommand thisCommand = new SqlCommand("SELECT CustomerID,
CompanyName from Customers", thisConnection);
Exemple de sélection
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 122
Exemple de mise à jour
5. Utiliser un DataSet
Un dataset permet l’accès déconnecté à une BD. Dans ce cas, on se connecte pour charger le
DataSet et on se déconnecte aussitôt. Les raisons pour l’utilisation d’un dataset sont
nombreuses :
• Faire quelque chose qui consomme beaucoup de temps avec les données,
• Utiliser la liaison de données ASP.NET pour remplir un contrôle Web (une grille) avec les
données. Dans ce cas l’approche par DataSet est plus simple,
• Pour naviguer dans les 2 sens dans les données (DataReader va uniquement vers
l’avant),
• L’utilisation du DataSet, permet de stocker plusieurs tables et de définir des relations
entre elles,
• Pour enregistrer les données dans un fichier pour une utilisation ultérieure puisqu’un
DataSet peut être sauvegardé au format XML dans un fichier ordinaire.
Les applications ADO.NET utilisent le DataSet pour stocker des données, mais pas pour faire
des mises à jour. Pour faire des update, il est préférable d’utiliser des commandes directes.
Pour extraire des enregistrements et les placer dans un DataSet, il faut utiliser un DataAdapter.
Chaque DataAdapter peut contenir quatre commandes:
SelectCommand, InsertCommand, UpdateCommand et DeleteCommand.
Cela permet d'utiliser un seul Objet DataAdapter pour des tâches multiples.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 123
Exemple avec un DataSet
6. Utiliser des Relations
L’exemple suivant illustre l’utilisation des relations dans ADO.NET
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 124
7. Commandes paramétrées
Pour éviter les injections SQL est pouvoir utiliser des champs contenant des caractères spéciaux
tels que les apostrophes, il faut utiliser des commandes paramétrées.
Exemple :
SqlCommand thisCommand = new SqlCommand("INSERT into Film (nom_realisateur,
Titre ) values ( @param1 , @param2)", maConnection);
SqlParameter param1 = new SqlParameter("@param1", SqlDbType.VarChar);
SqlParameter param2 = new SqlParameter("@param2", SqlDbType.VarChar);
param1.Value = TxtRealisateur.Text;
param2.Value = txtTitreFilm.Text;
thisCommand.Parameters.Add(param1);
thisCommand.Parameters.Add(param2);
thisCommand.ExecuteNonQuery();
3. Introduction à Entity Framework
L’intégration du code SQL dans le C# est délicat et long à déboguer. Avec Entity Framework
Microsoft propose un mapping objet-relationnel avancé.
Entity Framework est une technologie qui permet de créer une couche d'accès aux données
(DAL pour Data Access Layer) liée à une base de données relationnelle. Il propose la création
d'un schéma conceptuel composé d'entités (en fait des classes) qui permettent la manipulation
d'une source de données, sans écrire une seule ligne. Entity Framework assure l'indépendance du
schéma conceptuel (entités ou objets) du schéma logique de la base de données - les tables.
Pratique :
1. Créez une BD Contacts et une table Contact selon le schéma suivant :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 125
2. Créez un projet console GestionDesContacts
3. Faites un clic droit sur le projet  Ajouter  Nouvel Élément  Modèle de donnée
ADO.NET entité. Nommez le nouvel objet Contact.edmx. Puis cliquez sur Ajouter.
Choisir Générer à partir de la BD. Dans l’écran suivant choisir la chaîne de connexion qui
correspond à votre base de donnée (ici Contacts.dbo) puis cliquez sur Suivant.
4. Incluez les tables qui vous intéressent puis cliquez sur Terminer.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 126
Vous devriez obtenir ceci dans votre application :
Si vous affichez les classes de votre projet (en cliquant sur Class View), vous devriez
voir apparaître 2 nouvelles classes qui ont été créées à partir de la BD :
5. Désormais pour manipuler la BD on passera par ces classes, et donc plus besoin de
rédiger le code nécessaire pour ouvrir la connexion, créer les commandes et les exécuter.
Entity Framework se charge de tout.
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 127
6. Exemple : Voilà le code pour ajouter un contact et l’insérer à la BD. Ce code utilise les 2
classes ContactEntities et Contact pour réaliser ces opérations :
Le langage C# Collège Maisonneuve
Fayçal Abouzaid Page 128
Références
Beaucoup d’exemples sont adaptés de :
Sam A. Abolrous, Learn C#, Wordware Publishing, Inc., 2008
Autres références utilisées:
Christian Nagel, Jay Glynn, Morgan Skinner, Professional C# 5.0 and .NET 4.5.1, Wiley
Publishing, 2014
John Sharp, Microsoft Visual C# 2010 étape par étape, Microsoft Press, Dunod, 2010.
Christain Nagel & al, Professional C#4 and .NET4, Wiley Publishing, 2010.
Serge Tahé , APPRENTISSAGE DU LANGAGE C# 2008 et du Framework .NET 3.5
- ISTIA - Université d'Angers, Mai 2008.
Microsoft : http://msdn.microsoft.com/fr-ca/vcsharp/aa336706

Introduction á C-sharp

  • 1.
    Automne 2018 Le LangageC# Support de cours Fayçal Abouzaid
  • 2.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 2 Sommaire 1. Présentation du .NET Framework........................................................................................... 6 1.1 Objectifs............................................................................................................................. 7 1.2 Vue générale de l’architecture .NET ............................................................................... 7 1.3 Les Langages .NET.......................................................................................................... 8 1.4 Common Language Runtime........................................................................................... 8 1.5 Les différents types d’applications................................................................................... 9 1.6 Assemblages....................................................................................................................... 9 1.7 Environnement de développement ................................................................................ 10 1.8 Premier projet C# : Quelques concepts......................................................................... 11 1.9 Les interfaces graphiques ............................................................................................... 12 2. Éléments de base du langage C#........................................................................................... 14 2.1 Historique du langage C# .............................................................................................. 14 2.2 Conventions pour l’écriture des programmes................................................................ 14 2.3 Les types en C# ............................................................................................................... 15 2.4 Les opérateurs.................................................................................................................. 19 2.5 Les caractères et les chaînes de caractères.................................................................... 20 2.6 LesTypes nullables.......................................................................................................... 23 2.7 Les énumérations : Enum............................................................................................... 23 2.8 Les expressions régulières : La Classe regex.............................................................. 24 3 Les structures de décision et de répétition............................................................................ 28 3.1 Les opérateurs.................................................................................................................. 28 3.2 Les instructions de décisions.......................................................................................... 29 3.3 Les instructions de répétitions ....................................................................................... 31 3.4 Les tableaux..................................................................................................................... 33 4 Classes et objets....................................................................................................................... 37 4.1 Introduction..................................................................................................................... 37 4.2 Classes.............................................................................................................................. 37 4.3 Les structures : Struct...................................................................................................... 49 4.4 Visual Studio et les classes.............................................................................................. 51 4.5 Classes .NET d’usage courant ....................................................................................... 52
  • 3.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 3 5 Les fonctions membres........................................................................................................... 54 5.1 Définition des fonctions membres................................................................................. 54 5.2 Méthodes virtuelles et redéfinies.................................................................................... 54 5.3 Classes et méthodes abstraites ....................................................................................... 57 5.4 Surcharge de méthodes................................................................................................... 58 5.5 Passage de Paramètres.................................................................................................... 59 5.6 Propriétés sous la forme d’expressions.......................................................................... 61 5.7 Les indexeurs................................................................................................................... 61 5.8 La surcharge des opérateurs........................................................................................... 63 5.9 Les attributs ..................................................................................................................... 64 6 Les Exceptions ........................................................................................................................ 66 6.1 Erreurs et exceptions....................................................................................................... 66 6.2 Lancer une Exception..................................................................................................... 66 6.3 Exemples d’exceptions : ................................................................................................. 66 6.4 Capturer une Exception.................................................................................................. 67 6.5 Organisation des gestionnaires ...................................................................................... 68 6.6 Instruction try-finally ............................................................................................ 68 6.7 Instruction try-catch-finally.............................................................................. 68 6.8 Exceptions personnalisées.............................................................................................. 69 6.9 Relancer une exception................................................................................................... 70 6.10 Utilisation de StackTrace........................................................................................... 70 6.11 Opérateur de condition null : ?. (C#6)........................................................................ 71 6.12 Filtres d’Exceptions (C#6) ............................................................................................. 71 6.13 Nameof (C#6)............................................................................................................... 72 7 Délégués et Événements......................................................................................................... 73 7.1 Définition d'un délégué .................................................................................................. 73 7.2 Déclaration des délégués ................................................................................................ 73 7.3 Création du délégué ........................................................................................................ 74 7.4 Invocation du délégué..................................................................................................... 74 7.5 Associer un délégué à plusieurs méthodes.................................................................... 75 7.6 Ajouter ou supprimer des délégués................................................................................ 76
  • 4.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 4 7.7 Utiliser les méthodes .NET............................................................................................ 78 7.8 Les événements ............................................................................................................... 78 8 Les Interfaces........................................................................................................................... 81 8.1 Déclaration de l’interface................................................................................................ 81 8.2 Membres........................................................................................................................... 81 8.3 Implémentation de l’interface ........................................................................................ 82 8.4 Utiliser is pour tester les types...................................................................................... 83 8.5 Utiliser as pour convertir................................................................................................. 84 8.6 Cacher les membres d’une classe de base..................................................................... 84 9 L’interface Graphique (WinForms)........................................................................................ 87 9.1 Contrôles .......................................................................................................................... 87 9.2 Boutons ............................................................................................................................ 89 9.3 Les étiquettes (Label)...................................................................................................... 89 9.4 Boîte de texte ................................................................................................................... 90 9.5 Les contrôles RadioButton et CheckBox....................................................................... 91 9.6 Le contrôle RichTextBox................................................................................................ 92 9.7 Les contrôles ListBox et CheckedListBox .................................................................... 94 9.8 Menus............................................................................................................................... 95 10 Introduction à Windows Presentation Foundation........................................................... 96 10.1 Introduction..................................................................................................................... 96 10.2 Principales caractéristiques de WPF.............................................................................. 96 10.3 Créer une application WPF simple ................................................................................ 97 10.4 Contrôle TextBox............................................................................................................ 99 10.5 Contrôle Bouton Radio............................................................................................... 100 10.6 Ajouter supprimer dynamiquement un élément ......................................................... 101 10.7 Créer un Menu............................................................................................................... 101 11 Collections et itérateurs - Génériques.............................................................................. 104 11.1 Exemples de collections................................................................................................ 104 11.2 La classe non générique ArrayList............................................................................... 104 11.3 Utilisation des énumérateurs........................................................................................ 106 11.4 Itérateurs ........................................................................................................................ 108 11.5 Les collections génériques............................................................................................ 109
  • 5.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 5 12 ADO.NET.......................................................................................................................... 115 12.1. SQL Server et Visual Studio.......................................................................................... 115 12.2. Les Bases de ADO.NET............................................................................................... 117 Références .......................................................................................................................................... 128
  • 6.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 6 1. Présentation du .NET Framework “The .NET Framework is an integral Windows component for building and running the next generation of software applications and Web services.” Le Framework .NET est un ensemble d’outils de programmation proposés par Microsoft qui permettent au programmeur de développer différents types d’applications : des applications console, Windows Form ou WPF, des services Web, des applications Windows mobile et bien d’autres. La dernière mouture en date du Framework .NET est la version 4.7. Les différentes dates de sorties des différentes versions présentées dans le tableau ci-dessous. Chaque mise à jour apporte son lot de nouveautés et d’améliorations. Version Date Visual Studio Distribué avec 1.0 Février 2002 Visual Studio Windows XP Tablet and Media Center Editions 1.1 24 Avril 2003 Visual Studio 2003 Windows Server 2003 2.0 7 Novembre 2005 Visual Studio 2005 Windows Server 2003 R2 3.0 6 Novembre 2006 Windows Vista, Windows Server 2008 3.5 19 Novembre 2007 Visual Studio 2008 Windows 7, Windows Server 2008 R2 4.0 12 Avril 2010 Visual Studio 2010 4.5 15 Aout 2012 Visual Studio 2012 Windows 8, Windows Server 2012 4.5.1 17 Octobre 2013 Visual Studio 2013 4.5.2 5 Mai 2014 4.6 20 Juillet 2015 Visual Studio 2015 Windows 10, Windows Server 2016 4.7 5 Avril 2017 Visual Studio 2017 Windows 10 Creators Update 4.7.1 Octobre 2017 4.7.2 Avril 2018 Core SDK 2.1.5 (Source Wikipedia) Visual Studio Community est désormais gratuit. Il peut être téléchargé à l’adresse : https://www.visualstudio.com/fr-fr/downloads
  • 7.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 7 1.1 Objectifs Les objectifs du .NET Framework sont nombreux. On peut citer : • Une approche unifiée pour la conception d’applications : Win, Web, services, … • Des facilités pour le développement et le déploiement d’applications, • Une grande facilité d’intégration et interopérabilité entre différents composants. Le Framework est constitué de deux composants: • Le Common Language Runtime (CLR) qui est l’environnement d’exécution des applications .NET • Une librairie de classes unifiée partagée par les différents langages, la .NET Class Library. 1.2 Vue générale de l’architecture .NET La Common Language Specification (CLS) est une spécification qui gère la compatibilité des langages avec le Framework, ce qui permet d’utiliser n’importe quel langage compatible, qui sera ensuite compilé par son compilateur associé qui produira un programme en code intermédiaire (Common Intermediate Language - CIL) anciennement MicroSoft Intermediate Language (MSIL). Le programme CIL sera ensuite traduit par la Common Language Runtime (CLR) en code natif sur n’importe que plateforme où elle sera installée. La CLR traduit le CIL selon les besoins spécifiques de l’application et de la machine hôte, c’est ce qui s’appelle la compilation ‘Just in Time’ (JIT) et qui optimise donc les performances. Ce fonctionnement largement inspiré de celui de la machine virtuelle JAVA, facilite la migration d’un langage de développement spécifique vers la plateforme .Net (exemple du Visual Basic vers le VB.Net).
  • 8.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 8 L’architecture générale de la plateforme .NET est représentée par le schéma suivant : 1.3 Les Langages .NET Tous les langages .NET sont nés égaux : • Pas de différences fonctionnelles car plusieurs fonctionnalités ont été déplacées du langage au framework comme par exemple les accès aux fichiers. • Les différences sont surtout au niveau syntaxique et au niveau de certaines caractéristiques bien précises. • Il n’y a pas de différences de performances pour le code managé, c-à-d, exécuté par le CLR. • Tous les langages sont compilés en CIL et exécutés par la CLR. • Il y a un grand niveau d’interopérabilité (cross-languages) ce qui fait que l’on peut dériver en VB.NET une classe écrite en C#, par exemple. 1.4 Common Language Runtime “The common language runtime is the execution engine for .NET applications” Le CLR fournit un certain nombre de services, notamment :
  • 9.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 9 • Le chargement et l’exécution du code, • La compilation Juste-à-temps (JIT) qui réalise la conversion du code IL en code natif, • La vérification de type (Common Type System), • La gestion des exceptions, • La gestion de la mémoire via le ‘garbage collector’ (ramasse-miettes), • L’enregistrement dynamique des composants, • Les contrôles de sécurité. 1.5 Les différents types d’applications Les différents types d’applications que l’on peut développer dans l’environnement .NET sont : • Les interfaces utilisateurs Windows (Windows Forms ou Windows Presentation Foundation (WPF) qui est une spécification graphique plus récente de Microsoft .NET), • Les applications en mode console Windows, • Les services Windows, • Les services Web, Windows Communication Foundation (WCF), • Les applications Web, en particulier grâce à ASP.NET. 1.6 Assemblages .NET regroupe les composants en assemblages (assemblies). Ce sont des fichiers avec l’extension .dll ou .exe qui contiennent les classes compilées. La notion d’assemblage remplace les notions classiques de dll et exe. Le compilateur ne génère plus de code machine mais génère un assemblage. L’assemblage est constitué de deux parties : • Le langage intermédiaire (Intermediate Language - IL) qui est le code (DLL), et • Le Metadata qui contient le manifeste décrivant le contenu de l’assemblage : nom, version, signature, liste des fichiers, dépendances avec d’autres assemblages, infos de sécurité, … Chaque fichier a un nom et une clé cryptée permettant de l'authentifier. 1.6.1 Avantages des assemblages L’utilisation des assemblages présente de nombreux avantages dont : • L’enfer des DLLs résolu par une gestion plus restrictive des versions, • La CLI traite les types de même noms comme distincts s’ils viennent de 2 assemblages différents (multi-langages), • La base des registres n’est plus sollicitée (les applications sont auto-descriptives), • Les assemblages sont infalsifiables, • Les assemblages sont prévus pour être portables, • Un assemblage peut être morcelé en plusieurs fichiers.
  • 10.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 10 1.6.2 Structure d’un assemblage 1.7 Environnement de développement 1.7.1 Présentation Microsoft Visual studio 2013 est un environnement puissant de développement dédié au.NET Framework. Cependant son utilisation n’est pas obligatoire puisque les programmes C# peuvent être compilés en ligne de commande par un compilateur C#. Assemblage Foo2.netmodule Métadonnées de type Code IL des méthodes des types Ressources (image, sons …) Foo1.exe Image.jpg Manifeste Ref ver Foo2 Ref ver Image.jpg méthodes des types Code IL des méthodes des types
  • 11.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 11 1.7.2 Les types de projets et les templates À la création d’un nouveau projet, Visual Studio propose de choisir entre différents langages de programmation et différents types d’applications. 1.8 Premier projet C# : Quelques concepts Structure générale − solution − projet − classe (!) − point d’entrée − namespaces Clause « using » Commentaires : //, /* */ Doc Comments: /// output: html/xml Références AssemblyInfo Sensible à la casse
  • 12.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 12 .NET permet de créer une solution pouvant contenir plusieurs projets indépendants ou reliés par l’intermédiaire des références. Chaque projet se compose d’au moins une classe - il en contient en fait plusieurs. Pour chaque projet, on définit un point d’entrée (méthode Main()). Un projet peut faire partie d’un espace de nom (namespace) qui permet de mieux organiser le code. La directive « using» au début du programme, permet d’indiquer les bibliothèques qui sont nécessaires au projet, ce qui évite d’écrire à chaque fois le chemin complet des objets externes que nous utilisons. Ainsi on écrira «Console.WriteLine » au lieu de «System.Console.WriteLine». 1.9 Les interfaces graphiques - Win Forms : C’est l’interface graphique de .NET qui fournit l’accès via la CLR à l’API Windows. On peut donc créer grâce aux WinForms des applications graphiques intégrants des fenêtres et plusieurs types de boutons réagissant à des évènements tels que les clics de souris. - Windows Presentation Foundation (WPF) est une spécification graphique introduite depuis le Framework 3.0. Il intègre le langage descriptif XAML. Il est entièrement vectoriel, pour le dessin comme pour le texte. Cela permet d'augmenter la taille des objets en fonction de la résolution de l'écran sans effet de pixelisation.
  • 13.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 13
  • 14.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 14 2. Éléments de base du langage C# 2.1 Historique du langage C# • Version 1 : début 2001 • Version 2.0 : Visual studio 2005 ; o Ajout des génériques, des itérateurs et des méthodes anonymes; • Version 3.0 : Visual studio 2008 o Méthodes d’extension, les expressions lambda, LINQ (langage de requêtes); • Version 4.0 : Visual studio 2010 o Bibliothèque parallèles de tâches (pour processeurs multi-cœurs), meilleure prise en charge des services Web (modèle REST ou SOAP) et des WCF (Windows Communications Foundation). • Version 5.0 (Juin 2013) : Visual studio 2012. o Méthodes asynchrones; o Attributs améliorés. • Version 6.0 (Avril 2015) : Visual studio 2015. o Filtres d’exceptions; o Auto-initialisation des propriétés; o Catch et finally asynchrones; o Constructeurs primaires … • Version 7.1 (Août 2017) : Visual studio 2017. o Main asynchrone avec de nouvelles syntaxes pour Main(); o Expressions Littérales par défaut ; o Tuples ; o Pattern matching générique ; 2.2 Conventions pour l’écriture des programmes • Les noms des classes, structs, et méthodes commencent par une lettre majuscule (exemple, Class1et Methode1). Si le nom est constitué de mots joints, on met en majuscules le début de chaque mot (par exemple: MaPremiereClasse, CalculeTonSolde). • Commencer les noms des interfaces avec la lettre “I” (par exemple: IMonInterface et IInterface1). • Les noms des variables locales commencent par une minuscule et la première lettre de chaque mot suivant est en majuscules (exemple: maVariable, tonInt, ou monDoubleTypeVariable). • Il conseillé d’utiliser des noms de variables significatifs qui indiquent la signification de ce qu’ils représentent : monNumeroCompte ou tonNAS.
  • 15.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 15 • L’accolade ouvrante ({) doit être sur une nouvelle ligne sous la déclaration de classe ou de membre. L’accolade fermante (}) est placée sur la même colonne sur une ligne distincte. • Il faut laisser une ligne vide après chaque opération distincte : déclarations de variables, boucles ou tests. 2.3 Les types en C# Un programme C# est une collection de types : Classes, interfaces, structures, délégués ou énumérations. C# fournit un ensemble de types prédéfinis : int, byte, char, string, object,… Mais on peut aussi définir ses propres types. Les types sont des données membres d’une classe : Champs, constantes, tableaux ou évènements Ce sont aussi des fonctions membres d’une classe : Méthodes, opérateurs, constructeurs, propriétés et indexeurs Ce peut être encore d’autres types. Il y a 2 catégories de types: les types valeur et les types référence. 2.3.1 Types valeurs et références Le Type Valeur contient des données et ne peut avoir la valeur ‘null’. Il est constitué de : - Primitives int i ; float x; - Enumérations enum State { Off, On } - Structures struct Point {int x, y;}
  • 16.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 16 Le Type référence : contient des références vers des objets et peut être ‘null’. Il est constitué de : - Racine object - Chaîne string - Classes class Foo: Bar, IFoo {… } - Interfaces interface IFoo: IBar {… } - Tableau string[] a = new string [10] - Delegates delegate void Empty(); Remarquez que le type string est un cas particulier. C’est un type référence qui se comporte comme un type valeur. •••• Les types valeur Les caractéristiques principales des types valeur sont: • Pas d’allocation dans le tas (heap en anglais) mais sur la pile (stack) ce qui implique une durée de vie limitée par la portée et moins de travail pour le GC, • Une meilleure utilisation de la mémoire, • Moins de références indirectes, • La copie physique lors de l’assignation et du passage des paramètres (sauf ref). Exemple
  • 17.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 17 •••• Les types Référence Les types référence héritent de System.Object. Ils sont introduits par les mots-clés : Class, array, delegate, interface, string La variable est une référence vers un objet alloué sur le tas; notez qu’on peut avoir plusieurs références vers un même objet. Les objets sont créés avec le mot-clé new et détruits automatiquement par le GC (Garbage Collector). Il n’y a pas de copie physique lors du passage de paramètres contrairement au type valeur. Il y a cependant une exception : le type string qui est un type référence qui se comporte comme un type valeur. 2.3.2 Boxing et Unboxing Les types valeurs ne sont pas alloués sur le tas. Comment peuvent-ils être utilisés dans des structures de données ou des méthodes qui attendent une référence? Pour cela, on aura recours à une conversion du type valeur vers une type référence (objet). Cette conversion est le « Boxing ». L’opération inverse, c’est-à-dire convertir un objet en type valeur, s’appelle « unboxing ». Elle est plus délicate et doit donc être explicitée, par l’utilisation d’un cast (conversion explicite). 2.3.3 Les types définis par l’utilisateur On peut définir ses propres types de variables qui seront alors pris dans la liste suivante : Énumérations enum Tableaux (Arrays) int[][], string[] Interface interface Type référence class Type valeur struct Pointeur de fonction delegate
  • 18.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 18 2.3.4 Les types prédéfinis .NET offre un certain nombre de types prédéfinis Le type entier Les autres types numériques
  • 19.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 19 2.3.5 Exemples de types 2.4 Les opérateurs Les opérateurs permettent d’effectuer des opérations arithmétiques sur les variables. - Opérateurs Arithmétiques : +, –, *, / - Opérateur Modulo : % - Opérateurs incrémentation et décrémentation : ++, –– 2.4.1 Les opérateurs d’affectation Exemple 2.4.2 Les opérateurs de comparaison Ils permettent de tester des conditions et renvoient une valeur booléenne (true ou false). <, >, <=, >=, ==, != Avec la signification habituelle.
  • 20.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 20 2.4.3 La conversion entre types Il y a 2 types de conversions : implicite et explicite selon que l’on précise ou non que l’on veut faire une conversion. Voici 2 exemples de conversion implicite licite : double maVar = 4 ; float maVar = 33 ; Les conversions implicites suivantes sont interdites : int x = 4 ; short z1 = x ; // erreur de compilation double y = 3.3 ; short z2 = y ; // erreur de compilation Il ne doit donc pas y avoir de conversion implicite vers un type plus petit. Pour une conversion explicite il faut utiliser un cast comme dans les exemples suivants : short z1 = (short)x ; short z2 = (short)y ; 2.5 Les caractères et les chaînes de caractères 2.5.1 Le type caractère : char Les caractères sont stockés comme des caractères Unicode sur 16 bits. Exemples : char monChar = 'A'; char monChar = 'x0041'; On peut faire un cast sur le code ASCII comme dans : char monChar = (char)65; 2.5.2 Le Type chaîne de caractères : string La déclaration et l’initialisation du type string sont comme suit: string monString = "Bienvenue dans le monde du string!"; La concaténation se fait avec les opérateurs : +, += string salut= "Salut"; string virgule= ", "; string monde = "Le monde!"; string monString = salut + virgule + monde;
  • 21.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 21 2.5.3 La classe StringBuilder Le type string est immutable, ce qui oblige à utiliser la classe StringBuilder pour changer le contenu d’un string : StringBuilder monString = new StringBuilder("Salut,"); Append monString.Append("World!"); Insert monString.Insert(6," "); //insérer un espace en 6ème // position 2.5.4 Diverses opérations sur les strings • Opérateur Egalité : == Console.WriteLine(tonString == monString); • Pour accéder à un caractère de la chaîne on utilise [] Console.WriteLine(monString[7]); • Le caractère @ évite d’utiliser l’échappement : Au lieu de : string monDoc = "C:DocumentsLettersfriends.doc"; On aura : string monDoc = @"C:DocumentsLettersfriends.doc"; 2.5.5 Exemple de lecture à partir du clavier
  • 22.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 22 2.5.6 Convertir les Strings en Nombres long monLong = Convert.ToInt64(monString); //convertir à long float monFloat = Convert.ToSingle(monString);//float double monDouble = Convert.ToDouble(monString);//double decimal monDecimal = Convert.ToDecimal(monString);//decimal On peut aussi utiliser Parse Single.Parse(monString) // float Decimal.Parse(monString) // decimal Double.Parse(monString) // double 2.5.7 Interpolation de chaînes (C# 6) Ce mécanisme permet d’insérer des variables dans des strings. string person = "Paul"; Console.WriteLine($"Bienvenue, {person}!"); On peut ainsi formater la chaîne : Console.WriteLine($"dépôt de {montant:C} dans le compte.n"); 2.5.8 Formatage des résultats On peut afficher les nombres sous différents formats qui sont : Currency : Format monétaire Console.WriteLine ("{0:C}", 1.2); // 1.2$ Console.WriteLine ("{0:C}", -1.2); // (1.2$) Décimal Console.WriteLine ("{0:D5}", 123); // 00123 Point fixe Console.WriteLine("{0:F2}", 12); // 12.00 – 2 chiffres après la virgule Console.WriteLine("{0:F0}", 12); // 12 – pas de chiffre après la virgule Numérique Console.WriteLine("{0:N}", 1230000000); // 1,230,000,000.00 Scientifique Console.WriteLine("{0:E}", 12300000); // 1.230000E+007
  • 23.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 23 Héxadecimal Console.WriteLine ("{0:X}", 123); // 7B Console.WriteLine ("{0:X}", 65535); // FFFF 2.6 LesTypes nullables Ils ont été introduits depuis C#2005. Ils servent à assigner la valeur null à une variable ce qui est utile pour les Bases de Données où l’on veut pouvoir représenter un champ vide. Déclaration: monType? maVariable; Exemples: int? monInt = null; bool? monBool = null; float? monFloat = 1.23F; On peut assigner une valeur par défaut à un type en utilisant l’opérateur ?? double? monDouble = null; double monDouble1 = monDouble ?? -1.0; 2.7 Les énumérations : Enum Les énumérations servent à grouper certaines constantes de même catégorie. Elles dérivent de la classe System.Enum.
  • 24.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 24 2.8 Les expressions régulières : La Classe regex Les expressions régulières permettent de tester le format d'une chaîne de caractères. On peut par exemple vérifier qu'une chaîne représente une date au format "jj/mm/aa" ou qu’une adresse courriel est valide. Pour réaliser la comparaison, on utilise un modèle (motif) et on compare la chaîne de caractère à ce modèle. Les expressions régulières utilisent l’espace de noms : System.Text.RegularExpressions; qui fournit les méthodes: • IsMatch(String) : cette méthode indique si la chaîne d'entrée est conforme à l'expression régulière. • Match(String) : cette méthode permet de rechercher dans la chaîne d'entrée spécifiée la première occurrence de l'expression régulière. • Replace(String, String): Cette méthode permet de remplace Dans la chaîne d'entrée spécifiée, toutes les chaînes qui correspondent à un modèle d'expression régulière par une chaîne de remplacement spécifique. Les symboles utilisables dans un modèle sont les quantificateurs et les caractères spéciaux dont nous présentons les plus importants ci-après :
  • 25.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 25 2.5.1 Les Quantificateurs Symbole Résumé * Correspond à 0 ou plusieurs occurrences de l’expression qui précède. Exemple : 'zo*' correspond à "z" et "zoo". + Correspond à 1 ou plusieurs occurrences de l’expression qui précède. Exemple : 'zo+' correspond à "zo" et "zoo", mais pas à "z". ? Correspond à 0 ou 1 occurrence de l’expression qui précède. Exemple : 'zo(os)?' correspond à "zo" dans "zo" ou "zoos". {n} Correspond exactement à n fois le caractère. Par exemple, "o{2}" ne correspond pas à "o" dans "Bob," mais aux deux premiers "o" dans "fooooot". {n,} Correspond à au moins n fois le caractère. Par exemple, "o{2,}" ne correspond pas à "o" dans " Bob", mais à tous les "o" dans "fooooot". "o{1,}" équivaut à "o+" et "o{0,}" équivaut à "o*". {n,m} Correspond à au moins n et à au plus m fois le caractère. Par exemple, "o{1,3}" correspond aux trois premiers "o" dans "foooooot" et "o{0,1}" équivaut à "o?". x|y Correspond soit à x soit à y. Par exemple, "z|foot" correspond à "z" ou à "foot". "(z|f)oo" correspond à "zoo" ou à "foo". Les caractères spéciaux Symbole Résumé b Délimiteur : correspond à une limite représentant un mot, autrement dit, à la position entre un mot et un espace. Par exemple, "erb" correspond à "er" dans "lever", mais pas à "er" dans "verbe". t Tabulation. w Caractères (a-z, A-z, 0-9 et underscore). W Tout caractère qui n’est pas une lettre. Équivaut à "[^A-Za-z0-9_]". ^entre les crochets signifie non. s Correspond à tout espace blanc, y compris l'espace, la tabulation, le saut de page, etc. Équivaut à "[ fnrtv]". S Correspond à tout caractère d'espace non blanc. Équivaut à "[^ fnrtv]". d Chiffres (0-9). D Tout caractère qui n’est pas un chiffre. . Correspond à tout caractère unique, sauf le caractère de nouvelle ligne. $ Correspond à la fin de la saisie (chaîne ou ligne). ^ Correspond au début de la saisie
  • 26.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 26 2.5.2 Les Groupes Construction Signification () Définit un groupe simple. (?<name>) Groupe de nom "name" (?i:) Ignore la casse n Correspond au groupe précédent (groupe #n) Par exemple, (w)1 trouve les caractères doubles dans un mot. k<name> Correspond au groupe précédent spécifié par son nom (name). 2.5.3 Exemples d’utilisation des ER Voici quelques exemples d’utilisation des expressions régulières. Exemple 1 : expression régulière pour trouver des mots dupliqués string input; string pattern = @"b(w+)s1b"; input = Console.ReadLine(); Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase); MatchCollection matches = rgx.Matches(input); if (matches.Count > 0) { Console.WriteLine("{0} ({1} matches):", input, matches.Count); foreach (Match match in matches) Console.WriteLine(" " + match.Value); } Exemple 2 : Adresse email valide Regex valideMail = new Regex(@"^[a-zA-Z0-9_.-]{4,30}@{1}[a-zA-Zd.-]{3,63}.{1}[a-zA-Z]{2,4}$"); Console.Write("Votre courriel : "); string monCourriel = Console.ReadLine(); if (valideMail.IsMatch(monCourriel)) Console.WriteLine("adresse correcte!"); else Console.WriteLine("adresse incorrecte!");
  • 27.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 27 Exemple 3 : Suppression des espaces inutiles // Suppression des espaces inutiles string input = " Ce texte contient des espaces "; string pattern = "s+"; string remplacement = " "; Regex rgx = new Regex(pattern); string resultat = rgx.Replace(input, remplacement); Console.WriteLine("Chaîne d'origine: {0}", input); Console.WriteLine("chaîne transformée: {0}", resultat);
  • 28.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 28 3 Les structures de décision et de répétition 3.1 Les opérateurs Les différentes catégories d’opérateurs sont : - Les opérateurs de relation : >, >=, <, <=, ==(égal), !=(différent) - Les opérateurs logiques : &&, &, ||, | , ! Exemples : Si x=5, y=10 (x > 5) && (y == 10) // false - Le second opérande n’est pas évalué (x > 5) & (y ==10) // false (x == 5) || (y == 12) // true - Le second opérande n’est pas évalué (x == 5) | (y ==12) // true ! (x == 7) // true
  • 29.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 29 3.2 Les instructions de décisions 3.2.1 Les tests Le test d’une condition se fait par l’instruction if dont la syntaxe est la suivante : if (condition) instruction(s)_1 // Si condition vraie [else instruction(s)_2] // Si condition fausse Ce qui est entre [ ] étant facultatif. Exemple 3.2.2 L’instruction switch L’instruction switch permet de traiter plusieurs cas en une seule instruction. Sa syntaxe est la suivante : switch (expression) { case constante-1: instruction(s) instruction de saut case constante-2: instruction(s) instruction de saut case constant-3: ... ... [default: instruction(s) instruction de saut ] }
  • 30.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 30 Exemple Exécution en cascade du switch : tant que l’instruction switch n’a pas rencontré un break, l’exécution se poursuit en séquence. switch(n) { case 1: // descend jusqu’au cas 3 case 2: // descend jusqu’au cas 3 case 3: Console.WriteLine("case1 & 2 arrivent ici!"); break; // ... }
  • 31.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 31 3.2.3 Expression conditionnelle Une expression conditionnelle se fait grâce à l’opérateur ternaire ( ? : ) dont la syntaxe est : condition ? expression_siVrai : expression_siFaux Exemple: resultat = (x != 0.0) ? Math.Tan(x) : 1.0; Identique à : if (x != 0.0) resultat = Math.Tan(x); else resultat = 1.0; 3.3 Les instructions de répétitions Les instructions de répétitions se font par l’intermédiaire de boucles qui sont au nombre de 3 : for, while et do while. 3.3.1 Boucle for La boucle « for » correspond à la structure « Pour » en algorithmique. Sa syntaxe est la suivante : for ([initialisation]; [contrôle]; [incrémentation]) instruction(s) Exemple : for (int compteur = 1; compteur <= 5; compteur ++) { Console.WriteLine(compteur); } • continue et break Ces 2 instructions permettent de réaliser des ruptures de séquences dans les boucles. for (int compteur = 1; compteur <= 10; compteur +=2) if (compteur == 3) continue;  Permet de sauter directement à l’étape compteur = 4.
  • 32.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 32 for (int compteur = 1; compteur <= 10; compteur +=2) if (compteur == 7) break;  Sort de la boucle quand compteur == 7 Comme le montrent ces exemples, ils correspondent à des « goto » cachés et de ce fait, doivent être évités au possible. 3.3.2 Boucle while La boucle while correspond à l’instruction ‘Tant que’ en algorithmique. Sa syntaxe est : while (expression) instruction(s); L’instruction peut ne pas s’exécuter si l’expression est fausse. Exemple: int compteur = 1; while (compteur != 0) { compteur ++; if (compteur == 2) continue; // Saute la valeur 2 if (compteur > 5) break; // Termine la boucle console.WriteLine(compteur ); } 3.3.3 Boucle do-while La boucle « do while » traduit une instruction du type « répéter jusqu’à » et sa syntaxe est donnée par : do instruction (s) while (expression); Exemple : int x = 0; do { x++; if (x%2 != 0) // si le nombre est impair continue; if (x == 8) break; // termine la boucle console.WriteLine(x); } while(x < 100);
  • 33.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 33 3.4 Les tableaux Les tableaux permettent de stocker en mémoire des données du même type. En C#, un tableau (array) est un type référence qui contient une séquence de variables d’un type donné (classe System.Array) Exemples de tableaux :
  • 34.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 34 Tableaux multi-dimensionnels Tableau multidimensionnel rectangle int[,] matrice = new int [3,8] Accès aux éléments : matrice[0,0] = 133; Tableau multidimensionnel en escalier int[][] tbl = new int[8][]; tbl[0] = new int[3]; tbl[1] = new int[4]; tbl[2] = new int[2]; tbl[3] = new int[4]; Accès aux éléments : tbl[1][3] = 43; Remarques sur les tableaux : Le contrôle des bornes se fait par le runtime, et en cas de dépassement l’exception IndexOfOutRangeException est levée. Il existe d’autres structures de données qui permettent une modification dynamique du nombre d’éléments. Voir la classe System.Collections qui contient les structures prédéfinies ArrayList, HashTable, … 3.4.1 Utilisation des Propriétés et Méthodes avec les tableaux Comme toute classe prédéfinie, la classe Array possède des propriétés et des méthodes prêtes à être utilisées et dont nous présentons quelques-unes : • La propriété Length donne le nombre d’éléments d’un tableau int[,] monArray= new int[10,4]; Console.WriteLine(monArray.Length); // Affiche 40 • La propriété Rank donne le nombre de dimensions d’un tableau int[,] monArray= new int[1, 3]; // 2 dimensions int[,,] tonArray= new int[10, 4, 5]; // 3 dimensions Console.WriteLine(monArray.Rank); // 2 Console.WriteLine(tonArray.Rank); // 3
  • 35.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 35 3.4.2 Utilisation des tableaux • La méthode Array.Sort permet de trier un tableau int[] monArray = { 3, 4, 56, 8 }; Array.Sort(monArray); // 3,4,8,56 • La méthode Array.Reverse permet d’inverser un tableau int[] monArray = { 3, 4, 8, 56 }; Array.Reverse(monArray); // 56,8,4,3 • Pour redimensionner un tableau on utilise Array.Resize int [] monArray = { 1, 2, 3 }; string[] tonArray = { "Tom", "Dick", "Harry" }; Array.Resize(ref monArray, 6); Array.Resize(ref yourArray, 6);
  • 36.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 36 3.4.3 La boucle foreach Une boucle foreach permet de parcourir les éléments d’une liste, a fortiori d’un tableau. Sa syntaxe est la suivante : foreach (type identificateur in expression) instruction(s); Exemple: int[,] monIntArray = { {1, 3, 5},{2, 4, 6} }; Console.WriteLine("nb d’éléments:{0}", monIntArray.Length foreach(int i in IntArray) Console.Write("{0} ", i);
  • 37.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 37 4 Classes et objets 4.1 Introduction 4.1.1 Limites de l’approche procédurale Les données et fonctions sont définies séparément. On doit donc passer les données en paramètre à chaque fonction. Ceci pose : • Le problème de la protection des données puisque les champs sont accessibles à tous ; • Le problème de l’encapsulation en général. 4.1.2 Encapsulation et concept d’objet En conception orientée objet, les données et les fonctions qui les manipulent sont regroupées dans une même entité : l’objet. Les détails d’implémentation sont donc cachés et l’extérieur n’a accès aux données qu’au travers de l’interface de l’objet. Les avantages sont nombreux : • Abstraction de données, • Modularité, • Facilités de modification (couplage faible), • Réutilisabilité, • Lisibilité des programmes: détails d’implémentation cachés. 4.2 Classes Ce sont des types référence définis par l’utilisateur. Elles sont similaires aux classes C++ ou Java. Leurs caractéristiques sont : • L’héritage simple sur la classe ; • Elles peuvent implémenter de multiples interfaces ; • Le contrôle de l’accès aux membres se fait par les modificateurs d’accès : public, private, internal, protected, protected internal • Le mode par défaut est private ; • Les membres des classes sont des : • Constantes, champs (fields), méthodes, opérateurs (constructeurs et destructeurs); • Propriétés, indexeurs, évènements ; • Membres par classe (static) ou par instance ; • Les classes sont instanciées par l’opérateur new.
  • 38.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 38 4.2.1 Ajout d’une classe dans VS 4.2.2 Exemple de classe Définition de variables et instanciation
  • 39.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 39 4.2.3 Niveaux d’accessibilité des classes Une classe peut avoir l’un des niveaux d’accessibilité suivants : Public : pas de restriction d’accès, Internal : accès limité aux classes du même assembly (par défaut). Les classes imbriquées peuvent également avoir l’un des niveaux d’accessibilité suivants : private: accès limité à la classe « englobant » protected: accès limité à la classe englobant et aux classes dérivées protected internal: accès limité aux classes de l’assembly et aux classes dérivées qui sont dans un autre assembly. Exemple d’accessibilité : class globale { protected class Point { public int x; //champs accessibles aux autres // classes. public int y; } class Program { static void Main(string[] args) { Point p1 = new Point(); p1.x = 33; p1.y = 22; Console.WriteLine("x = {0}, y = {1}", p1.x, p1.y); } } }
  • 40.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 40 4.2.4 Variables membres (champs) Une variable membre est caractérisée par : • Un niveau d’accessibilité • Un type • Une valeur par défaut (optionnelle) Exemple: protected string nomEmploye = "Durand"; Une variable peut être déclarée « static ». Elle est alors partagée entre les différentes instances de la classe. Exemple : public static string nomCompagnie; Une variable peut-être déclarée « readonly » pour empêcher sa modification après la construction de l’objet. Une valeur ne peut lui être assignée que lors de sa déclaration ou dans le constructeur. Exemple: public readonly int age = 45; Une constante doit avoir sa valeur fixée à la compilation. Exemple: protected const int NBMAX = 100; 4.2.5 Fonctions membres et méthodes Les fonctions membres (méthodes) sont déclarées et implémentées au même endroit. Elles sont caractérisées par : • Un niveau d’accessibilité, • Un type de retour (éventuellement void) et • Une liste de paramètres. Exemple : public int MaMethode() {} L’accessibilité est private par défaut. Une méthode peut être déclarée « static ». On l’appelle alors via le nom de la classe et non pas via une instance.
  • 41.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 41 Depuis la version 4, il y a des paramètres par défaut en C#. On peut donc définir une fonction en précisant des valeurs par défaut à certains paramètres, comme dans l’exemple : void optMethode(int un, double deux=0.0, string trois="salut") Un appel possible à cette méthode est : optMethode(99); Par défaut, les paramètres sont passés par valeur. Il existe cependant un autre type de passage de paramètres via ref. • Surcharge de méthodes : la signature d’une méthode est caractérisée par son nom et la signature des paramètres (y compris le type de passage des paramètres). Une méthode peut également être déclarée « sealed », ce qui empêche de la surcharger dans une classe dérivée. 4.2.6 Les propriétés Les propriétés sont un mécanisme pour exposer des données. De l’extérieur, cela ressemble à une variable publique. Elles permettent de cacher les détails d’implémentation et d’ajouter un traitement additionnel (validation, tracing, …). Exemple: Depuis C# 3.0 il est possible d'implémenter les propriétés automatiquement ; ce qui rend la déclaration de propriété plus concise quand aucune logique supplémentaire n'est requise dans les accesseurs de propriété. public string Nom { get; set; } public int ClientID { get; set; } Depuis C#6, il est possible de les initialiser : public string Prenom { get; set; } = "Jane"; Public class Personne { private string nom; public string Nom { get {return nom;} set {nom = value;} } } Personne unePersonne = new Personne (); unePersonne.Nom = "Dupont"; Création automatique dans VS: Bouton droit  Refactoriser  Encapsuler le champ.
  • 42.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 42 4.2.6.1 Propriétés statiques
  • 43.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 43 4.2.6.2 Propriétés readonly On peut définir une propriété en lecture seule en ne fournissant que le code du get : Les propriété auto-implémentée en lecture seule ne peuvent être initialisées que dans leurs déclarations ou dans les constructeurs. En C#6 il est possible d’initialiser une propriété auto-implémentée dans sa déclaration en utilisant la syntaxe suivante : Type PropertyName { get; set; } = initializer; public class Produit { public decimal Prix { get; set; } = 10.25; }
  • 44.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 44 4.2.6.3 Accessibilité des accesseurs Chaque accesseur a sa propre accessibilité : public string NomEmploye { get { return nomEmploye;} protected set { nomEmploye = value; } } Les modificateurs d'accès ne sont autorisés que sur l'un des accesseurs – habituellement set. Si l’on a qu’un seul accesseur, alors il n’y a pas de modificateur d'accès sur l'accesseur. 4.2.7 Constructeur et destructeur Le constructeur et le destructeur sont deux méthodes particulières qui sont appelées respectivement à la création et à la destruction d'un objet. 4.2.7.1 Constructeurs Caractéristiques du constructeur : • Un constructeur est une fonction membre dont le nom est le même que celui de la classe ; • Un constructeur n’a pas de type ; • On peut avoir plusieurs constructeurs ; • En fonction du nombre et du type des arguments passés à l’appel, le bon constructeur est choisi. Il y a 3 catégories de constructeurs : • Constructeurs d’instance : Ce sont les constructeurs les plus fréquents et parfois appelés juste ‘constructeurs’. Ils portent le même nom que la classe, et sont invoqués lors de la création d’un nouvel objet. • Constructeurs privés : Ils ne sont utilisés qu’avec des classes qui ne contiennent que des membres statiques. • Constructeurs statiques : Ils sont utilisés pour initialiser une classe. Ils sont appelés avant la création de tout objet et avant tout appel à un membre statique de la classe.
  • 45.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 45 Exemple de constructeur d’instance class Point { public int x, y; // Constructeur par défaut : public Point() { x = 0; y = 0; } // Un constructeur avec des paramètres public Point(int x1, int y1) { x = x1; y = y1; } } class MaClasse { static void Main() { Point p1 = new Point(); Point p2 = new Point(2, 10); Console.WriteLine("Premier Point : ({0}, {1})", p1.x, p1.y); Console.WriteLine("Deuxième Point : ({0}, {1})", p2.x, p2.y); } } 4.2.7.2 Mot clé « this » this est une référence sur l’objet courant qui est utilisée pour accéder aux données membres dans un constructeur d'instance (ou des méthodes accesseurs). Dans ce cas, on peut utiliser les mêmes noms pour les champs et les paramètres. Ce mot-clé ne peut être utilisé avec les constructeurs statiques ou les champs. 4.2.7.3 Constructeurs privés Ils sont utilisés avec des classes qui ne contiennent que des membres statiques. Les autres classes, sauf celles imbriquées dans la même classe, ne sont pas autorisées à créer des instances de cette classe. public class MaClasse { private MaClasse() {} // private constructor public string nomCompagnie; public string dateEmbauche; }
  • 46.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 46 Le constructeur privé est un constructeur vide dont le travail est d'empêcher la génération d'un constructeur par défaut pour la classe. Ainsi, l’instruction : MaClasse mc = new MaClasse(); Provoque une erreur de protection. Il est préférable de déclarer static une classe qui ne contient que des membres statiques. 4.2.7.4 Constructeurs statiques Les constructeurs statiques sont utilisés pour initialiser une classe ou n'importe quelle donnée statique, ou pour effectuer une action particulière devant être effectuée une seule fois. Ils sont appelés avant la création de tout objet et avant tout appel à un membre statique de la classe. class MaClasse { // Constructeur statique static MaClasse() { Console.WriteLine("Je suis le constructeur statique! " + "Je suis appelé automatiquement!"); } public void MaMethode() { Console.WriteLine("Je suis MaMethode. J'ai été appelée après " + "le constructeur statique!"); } } public class MaClasse { public static void Main() { MaClasse monObjet = new MaClasse(); monObjet.MaMethode(); } } 4.2.7.5 Héritage class MaClasseDerivee: MaClasseBase { // ... } La classe, MaClasseDerivee hérite de la classe MaClasseBase. Le symbole (:) est utilisé entre le nom de la classe dérivée et le nom de la classe de base. L’hérédité signifie que la classe dérivée contient tous les membres de la classe de base. On peut également ajouter de nouveaux membres aux membres hérités.
  • 47.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 47 4.2.7.6 Règles de contrôle de l'héritage: Tous les membres de la classe de base sont héréditaires (sauf les constructeurs d’instance, les destructeurs et les constructeurs statiques). Un membre dans la classe dérivée avec le même nom que dans la classe de base, cache ce dernier. Le membre de la classe de base n'est pas accessible par l'intermédiaire de la classe dérivée. Les fonctions membres dans la classe de base peuvent être remplacées par celles de la classe dérivée: polymorphisme. Une classe peut hériter d'une classe seulement (pas d’héritage multiple). Cependant, elle peut implémenter plus d'une interface. Les structures ne peuvent pas hériter de classes ou d’autres structures ni être héritées, mais elles peuvent implémenter des interfaces. Exemple class Citoyen { string identifiant = "111-2345-H"; string nom = "Pille Mandla"; public void GetInfosPersonnelles() { Console.WriteLine("Nom: {0}", nom); Console.WriteLine("Numéro de carte : {0}", identifiant); } } class Employe : Citoyen { string nomCompagnie = "Technology Group Inc."; string idCompagnie = "ENG-RES-101-C"; public void GetInfo() { // Appel à la méthode GetPersonalInfo de la classe de base: Console.WriteLine("Informations du Citoyen :"); GetInfosPersonnelles(); Console.WriteLine("nInformation sur son emploi :"); Console.WriteLine("Nom Compagnie : {0}", nomCompagnie); Console.WriteLine("ID Compagnie : {0}", idCompagnie); } } class MainClass { public static void Main() { Employe E = new Employe(); E.GetInfo(); } }
  • 48.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 48 4.2.7.7 Les destructeurs Les destructeurs sont utilisés pour détruire les objets. Un destructeur est déclaré ainsi: ~MaClasse() { // Instructions de destruction. } Ils portent le même nom que la classe, mais sont précédés par ~. Exemple de destructeur class Parent // parents { ~Parent() { Console.WriteLine("On appelle le destructeur de Parent."); } } class Enfant : Parent // enfants { ~Enfant() { Console.WriteLine("On appelle le destructeur de Enfant."); } } class GrandEnfant : Enfant // grand enfants { ~GrandEnfant() { Console.WriteLine("On appelle le destructeur de GrandEnfant."); } } public class MaClasse { public static void Main() { GrandEnfant monObjet = new GrandEnfant(); } }
  • 49.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 49 4.2.8 Classes partielles Il est possible de fractionner la définition d'une classe ou d'un struct, ou d'une interface sur deux fichiers sources ou plus. Chaque fichier source contient une section de la définition de classe, et toutes les parties sont combinées lorsque l'application est compilée. public partial class Employee { public void DoWork() { } } public partial class Employee { public void GoToLunch() { } } 4.2.9 Classes finales Lorsqu'il est appliqué à une classe, le modificateur ‘sealed’ empêche les autres classes d'en hériter. class A {} sealed class B : A {} Dans cet exemple, la classe B hérite de la classe A, mais aucune classe ne peut hériter de B. 4.3 Les structures : Struct Les structures sont similaires aux classes, mais diffèrent par un certain nombre de caractéristiques : - Ce sont des types valeur définis par l’utilisateur donc alloués sur la pile ; - Elles héritent toujours d’objet ; - Elles sont idéales pour des objets ‘légers’ ; - int, float, double, etc., sont des structures ; - Elles permettent la définition de types primitifs par l’utilisateur Complex, point, rectangle, color, rational - Elles supportent l’héritage multiple des interfaces ; - Elles ont les même membres que les classes ; - Les contrôles d’accès sont : public, internal, private; - Elles sont Instanciées par l’opérateur new; - Elles sont implicitement sealed, ce qui veut dire qu’il est impossible d'en hériter.
  • 50.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 50 Exemple 4.3.1 Classes et Structures class CPoint { int x, y; ... } struct SPoint { int x, y; ... } CPoint cp = new CPoint(10, 20); SPoint sp = new SPoint(10, 20);
  • 51.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 51 4.4 Visual Studio et les classes 4.4.1 Diagramme de classes Il est possible de créer ou de visualiser un diagramme de classes dans Visual studio. Celui-ci est accessible à partir de l’explorateur de solutions. Il permet de rajouter des classes et leurs membres. 4.4.2 Documentation XML On peut créer automatiquement une documentation XML pour documenter les classes et leurs membres. Pour cela on suit les étapes suivantes : Projet  Propriétés  Onglet Générer  Boîte sortie : spécifier un nom de fichier XML de documentation. Le fichier XML sera généré à la compilation et accessible à partir du répertoire du projet. Les balises de documentation précèdent n’importe quel membre du projet et sont introduites par ///. Exemples de balises proposées: <summary>, <para>, <param>, <description>, <permission>, <remarks>, …
  • 52.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 52 4.5 Classes .NET d’usage courant 4.5.1 Fonctions mathématiques Classe: System.Math Cette classe ne contient que des champs et méthodes statiques. Parmi les méthodes disponibles on peut trouver : Méthodes numériques multi-types: Abs, Min, Max et Sign Méthodes trigonométriques: Cos, Sin, … Méthodes puissances : log et exp Round, Ceiling, Floor Exemple: 4.5.2 Dates et intervalles de temps 2 classes sont disponibles : System.DateTime dont l’instance est une date. System.TimeSpan: dont l’instance est un intervalle de temps. Exemples: DateTime t = new DateTime(2014,10,19,18,0,0); string strDate = t.ToShortDateString(); string strTime = t.ToShortTimeString(); int day = t.DayOfYear; DateTime now = DateTime.Now; DateTime dans1Mois = t.AddMonths(1); DateTime t2 = Convert.ToDateTime("2014/10/20"); int nbJours = DateTime.DaysInMonth(2014,2); 4.5.3 Accès au système de fichiers L’espace de noms System.IO contient les classes permettant de manipuler les répertoires et les fichiers. Parmi les classes intéressantes on dénombre les classes pour : • La manipulation des répertoires: Directory et DirectoryInfo • La manipulation des fichiers: File et FileInfo • La manipulation des chemins d’accès: Path • La lecture / écriture dans des streams: StreamWriter et StreamReader, …
  • 53.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 53 Exemple: string srcPath = "c:temp"; if (!Directory.Exists(srcPath)) { Console.WriteLine("Le repertoire n'existe pas!"); } else { string[] lstRepertoires = Directory.GetDirectories(srcPath); string[] lstFichiers = Directory.GetFiles(srcPath); DirectoryInfo df = new DirectoryInfo(srcPath); foreach (FileInfo fileinfo in df.GetFiles()) Console.WriteLine(fileinfo.FullName); string testFilePath = srcPath + "test.txt"; StreamWriter sw = File.CreateText(testFilePath); sw.WriteLine("Test ...."); sw.Close(); }
  • 54.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 54 5 Les fonctions membres 5.1 Définition des fonctions membres Tous les membres d'une classe ou d’une structure (à l'exception des champs et des constantes) sont des fonctions membres : Méthodes Propriétés Événements Indexeurs Opérateurs définis par l’utilisateur Constructeurs Destructeurs • Le polymorphisme Soit, par exemple, une méthode appelée DessineFenetre. On peut associer cette méthode avec divers objets qui représentent les différents types de fenêtres. Selon l'objet associé à la méthode, le résultat va être différent. monBouton.DessineFenetre(); // dessine un bouton monMsg.DessineFenetre(); // dessine une message box maSurface.DessineFenetre(); //dessine une fenêtre à peindre 5.2 Méthodes virtuelles et redéfinies Pour utiliser les méthodes polymorphes on déclare la méthode DessineFenetre() avec le mot-clé virtual dans la classe de base: public virtual void DessineFenetre() { // La définition de la méthode est dans la classe de base. } Ensuite, dans chacune des classes qui héritent de la classe de base, on déclare une méthode DessineFenetre() en utilisant le mot-clé override: public override void DessineFenetre() { // La définition de la méthode est dans une des classes dérivées. }
  • 55.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 55 5.2.1 Redéfinition de méthode On peut redéfinir une autre méthode qui a le même nom, la signature et la même accessibilité que dans la classe de base. Quand on redéfinit une méthode, on peut changer son comportement d'origine dans la classe dérivée. Une méthode redéfinie peut redéfinir toutes les méthodes déclarées avec les modificateurs suivants: virtual abstract override Pour qu’une méthode redéfinisse celle de la classe de base, il faut modifier sa déclaration avec le mot-clé override. Une méthode abstraite est implicitement virtuelle, et donc peut-être redéfinie sans utiliser le modificateur virtual (elle ne peut pas de toute façon utiliser ce modificateur). On ne peut pas utiliser le modificateur virtual avec les modificateurs suivants: static, abstract ou override. On ne peut pas combiner le modificateur override avec les modificateurs suivants: static, abstract, virtual ou new. 5.2.2 Appel aux Membres de la Classe de base Si on désire appeler une méthode redéfinie de la classe de base on utilise le mot-clé base. base.GetInformation(); On ne peut pas utiliser le mot-clé base dans une méthode statique. S’il est nécessaire de construire l'objet de la classe de base avant de construire l'objet de la classe dérivée, on appelle le constructeur ainsi : public MaDerivee(int x) : base(x) { // ... } Ceci est le constructeur de la classe MaDerivee, qui construit l'objet de la classe de base à la volée.
  • 56.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 56 5.2.3 Redéfinition des méthodes Virtuelles de la Classe de Base // La classe de base : public class AiresClass { // champs: protected double x, y; // Constructeurs: public AiresClass() { } public AiresClass(double x, double y) { this.x = x; this.y = y; } // Méthodes: public virtual double Aire() { return 0; } } // La classe Point utilise un constructeur sans paramètres : class Point : AiresClass { public Point() : base() { } } // La classe Cercle : class Cercle : AiresClass { public Cercle(double r): base(r, 0) { } public override double Aire() { // L'aire d'un cercle. // Le rayon est représenté par x: return Math.PI * x * x; } } // La classe Sphere : class Sphere : AiresClass { public Sphere(double r): base(r, 0) { } public override double Aire() { // Le rayon est représenté par x: return 4 * Math.PI * x * x; } } // La classe Cylindre: class Cylindre : AiresClass { public Cylindre(double r, double h) : base(r, h) { } public override double Aire() { // x : rayon y : hauteur return 2*Math.PI *x*x + 2*Math.PI*x*y; }} class MaClasse { public static void Main() { // Lire les valeurs au clavier et les convertir: Console.Write("Entrer le rayon: "); double rayon = Convert.ToDouble(Console.ReadLine()); Console.Write("Entrer la hauteur: "); double hauteur = Convert.ToDouble(Console.ReadLine()); // Créer les objets: Point monPoint = new Point(); Cercle monCercle = new Cercle(rayon); Sphere maShpere = new Sphere(rayon); Cylindre monCylindre = new Cylindre(rayon, hauteur); // Afficher les résultats: Console.WriteLine("Aire du point = {0:F2}", monPoint.Aire()); Console.WriteLine("Aire du cercle = {0:F2}", monCercle.Aire()); Console.WriteLine("Aire de la sphère = {0:F2}", maShpere.Aire()); Console.WriteLine("Aire du cylindre = {0:F2}", monCylindre.Aire()); } }
  • 57.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 57 5.3 Classes et méthodes abstraites Le but d'une classe abstraite est d’être héritée par d'autres classes. Elle ne peut donc pas être instanciée. Une méthode abstraite est, par défaut, une méthode virtuelle. Elle ne peut exister qu'à l'intérieur d'une classe abstraite. abstract class MaBaseClasse // classe abstraite { public abstract void MaMethode(); // méthode abstraite ... } Les mots clés suivants ne sont pas permis dans la déclaration d’une méthode abstraite : static, virtual. Exemple : // Class abstraite : abstract class ClassDeBase { // Champs: protected int nombre = 100; protected string nom = "Dale Sanders"; // Méthode abstraite : public abstract void MaMethode(); // Propriétés abstraite : public abstract int Nombre { get; } public abstract string Nom { get; } } // Hériter de la classe: class MaClasseDerivee : ClassDeBase { // Surcharge des propriétés: public override int Nombre { get { return nombre; } } public override string Nom { get { return nom; } } // Surcharge de la méthode: public override void MaMethode() { Console.WriteLine("Nombre = {0}", Nombre); Console.WriteLine("Nom = {0}", Nom); } } class ClassePrincipale { public static void Main() { MaClasseDerivee monObjet = new MaClasseDerivee(); monObjet.MaMethode(); } }
  • 58.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 58 5.4 Surcharge de méthodes La surcharge de méthodes consiste à donner le même nom à plus d'une méthode et laisser le compilateur charger la méthode appropriée en fonction du nombre et du type de paramètres. Exemple: La fonction est surchargée int AuCarre(int x) double AuCarre (double f) Elle peut être appelée de 2 manières différentes : AuCarre (3.25); AuCarre (44); Note: Le lien entre la méthode spécifique et l'appel est fait au moment de la compilation, c’est ce que l’on appelle une liaison statique (ou anticipée). Un autre cas est possible quand les paramètres sont de même type mais en nombres différents. void MaMethode(int m1) { } void MaMethode(int m2, int m3) { } Exemple class MaClasse { // Paramètre de type string : static void MaMethode(string s1) { Console.WriteLine(s1); } // Paramètre de type entier : static void MaMethode(int m1) { Console.WriteLine(m1); } // Paramètre de type double : static void MaMethode(double d1) { Console.WriteLine(d1); } static void Main() { string s = "Voilà ma chaîne"; int m = 134; double d = 122.67; MaMethode(s); MaMethode(m); MaMethode(d); } }
  • 59.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 59 5.5 Passage de Paramètres Il y a deux façons de passer un paramètre à une méthode : • par valeur (passage par défaut) ou • par référence. 5.5.1 Passage par référence Le passage de paramètres par référence permet de modifier les valeurs des variables de manière persistante. Pour passer un paramètre par référence, on déclare le paramètre avec le mot-clé ref. Exemple // Exemple Permuter class MaClasse { static void Permuter(ref int x, ref int y) { int temp = x; x = y; y = temp; } static void Main() { int x = 25; int y = 33; Console.WriteLine("Avant la permutation: x={0}, y={1}", x, y); Permuter(ref x, ref y); Console.WriteLine("Après la permutation: x={0}, y={1}", x, y); } } Il y a trois modificateurs de paramètres, qui permettent la modification de la valeur des variables après le retour à la méthode appelante. Ces trois modificateurs sont : ref, out et params. Lorsqu’on utilise ref pour passer une variable à une méthode, la variable doit être initialisée en premier, sinon on génère une erreur du compilateur. Le modificateur out ne nécessite pas l'initialisation de la variable avant de la transmettre à la méthode, mais l'initialisation doit se faire dans la méthode elle-même. private void methodeTest(out int resultat) {} L’appel se fait par: methodeTest(out n); Le mot clé params est utilisé avec des tableaux. Il permet de transmettre n'importe quel nombre de paramètres à une méthode sans qu’il soit nécessaire de les déclarer dans un tableau. Ce mot clé est requis uniquement dans la déclaration de la méthode.
  • 60.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 60 Par exemple soit la fonction : static void MaMethode(params object[] monObjArray) L’appel à la méthode se fait par : MaMethode(123, 'A', "Ma chaine originale"); Les paramètres passés dans cet appel sont tous du type object, ce qui signifie qu’ils peuvent inclure tous les types hérités de la classe object. Exemple : public class MaClasse { // Déclaration de MaMethode qui utilise des paramètres entiers : public void MaMethode(params int[] monIntArray) { Console.WriteLine("Ma liste d'entiers originale:"); // Liste originale for (int i = 0; i < monIntArray.Length; i++) Console.WriteLine(monIntArray[i]); Console.WriteLine(); monIntArray[1] = 555; // Changer le 2ème élément Console.WriteLine("Ma liste d'entier après le changement:"); //après le changement for (int i = 0; i < monIntArray.Length; i++) Console.WriteLine(monIntArray[i]); Console.WriteLine(); } // Déclaration de MaMethode qui utilise des paramètres objets : public void MaMethode(params object[] monObjArray) { Console.WriteLine("Ma liste d'objets originale:"); //avant le changement for (int i = 0; i < monObjArray.Length; i++) Console.WriteLine(monObjArray[i]); Console.WriteLine(); // Changer le 3ème élément: monObjArray[2] = "Ma nouvelle chaîne"; Console.WriteLine("Ma liste d'objets après le changement:"); //après le changement: for (int i = 0; i < monObjArray.Length; i++) Console.WriteLine(monObjArray[i]); Console.WriteLine(); } } class MainClass { static void Main() { // Déclaration d'un tableau d'objets: object[] maObjListe = new object[] { 123, 'A', "Mon ancienne chaine" }; MaClasse mc = new MaClasse(); // Passer 4 entiers à la "première" MaMethode: mc.MaMethode(11, 22, 33, 44); // utiliser des paramètres numériques // Passer un tableau d'objets à la "2ème" MaMethode mc.MaMethode(maObjListe); // utiliser un tableau d'objets } }
  • 61.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 61 5.6 Propriétés sous la forme d’expressions C# 6 a introduit une syntaxe concise pour : • Méthodes qui contiennent seulement une instruction return ; • Propriétés read-only dans lesquelles get contient seulement un return ; • Méthodes qui contiennent une instruction simple. Exemple : La fonction : static int Cube(int x) { return x * x * x; } s’écrira en C#6 static int Cube(int x) => x * x * x; 5.7 Les indexeurs Les indexeurs, permettent de manipuler des classes comme des tableaux ou des collections. On peut donc accéder aux éléments de l’indexeur en utilisant les crochets ([]). Un indexeur est similaire aux propriétés puisqu’il peut aussi utiliser les accesseurs get et set pour exprimer ses caractéristiques. La déclaration d’un indexeur est de la forme: indexer-type this [parameter-type parameter] { get {}; set {}; }
  • 62.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 62 où: indexer-type est le type de l’indexeur. parameter-type est le type du paramètre. parameter est un paramètre ou une liste de paramètres Exemple class MaClasse { private string[] monTableau = new string[10]; // Déclaration de l'indexeur : public string this[int index] { get { return monTableau [index]; } set { monTableau [index] = value; } } } public class MainClass { public static void Main() { MaClasse s = new MaClasse(); // Utiliser l'indexeur pour initialiser les éléments #1 et #2: s[1] = "Tom"; s[2] = "Edison"; for (int i = 0; i < 5; i++) { Console.WriteLine("Element #{0}={1}", i, s[i]); } } } 5.7.1 Utilisation des indexeurs Il est courant d'utiliser les accesseurs set et get pour contrôler les limites de l'indexeur et éviter les erreurs. Par exemple: if (!(index < 0 || index >= 10)) // ... Il est permis aux interfaces d'avoir des indexeurs. Ils sont déclarés de la même manière avec les exceptions suivantes: - Les indexeurs des interfaces n’utilisent pas les modificateurs. - Il n'y a pas d’implémentation d’accesseurs dans les interfaces.
  • 63.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 63 5.8 La surcharge des opérateurs La surcharge permet d’assigner de nouveaux rôles pour certains opérateurs. Par exemple, on peut surcharger l’opérateur ‘+’ pour la classe Point : public static Point operator+(Point p1, Point p2) { // Implémentation de l’opérateur + // Voir exemple } D’autres exemples sont : operator-– , operator== Exemple public class Point { public int x; public int y; // Constructeur: public Point(int x, int y) { this.x = x; this.y = y; } // Surcharge de l'opérateur +: public static Point operator +(Point p1, Point p2) { // Retourner la somme comme un point: return new Point(p1.x + p2.x, p1.y + p2.y); } static void Main() { Point p1 = new Point(15, 33); Point p2 = new Point(10, 12); // Ajouter les 2 obbjets Point utilisant l'opérateur + surchargé: Point sum = p1 + p2; // Afficher les objets: Console.WriteLine("Point #1: ({0}, {1})", p1.x, p1.y); Console.WriteLine("Point #2: ({0}, {1})", p2.x, p2.y); Console.WriteLine("Sum of the two points: ({0}, {1})", sum.x, sum.y); } }
  • 64.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 64 5.8.1 Opérateurs surchargeables 5.8.2 Redéfinir la méthode ToString() Cette redéfinition est très utile pour l’affichage. Par exemple, au lieu de : Console.WriteLine("Point #1: ({0},{1})", p1.x, p1.y); On voudrait : Console.WriteLine("Point #1: {0}", p1); Pour cela on surcharge la méthode ToString(). On réalise la surcharge de la manière suivante : // Surcharge de la méthode ToString public override string ToString() { return (String.Format("({0}, {1})", x, y)); } 5.9 Les attributs Les attributs sont des informations additionnelles qui permettent de modifier les déclarations des entités de programme (types, membres, paramètres, etc., …). Ils servent à différentes choses comme par exemple marquer une méthode comme obsolète, indiquer une compilation conditionnelle, … Ils sont dérivés de la classe abstraite System.Attribute. L’attribut est mis entre [].
  • 65.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 65 Exemple: [method: DllImport("user32.dll")] C’est un attribut qui permet d’utiliser du code ‘unsafe’. Les éléments cibles des attributs sont: Assembly, field, event, method, parameter, property, return, type Autres exemples d’attributs Obsolète: [Obsolete("Vous devriez coder en Csharp! ", true)] public void CodeEnCPlusPlus() { // Le corps de la méthode obsolète. } Quand on compile cette méthode, le compilateur génère l’erreur : 'MaClasse.CodeEnCPlusPlus()' is obsolete: ‘Vous devriez coder en Csharp!‘. Si le 2ème paramètre est à false, le compilateur génère un warning, sinon c’est une erreur fatale. Conditionnel: [Conditional("MACONSTANTE")] public void MaMethode(string s) {} MaMethode n’est exécutée que si la constante MACONSTANTE est définie avec une directive: #define MACONSTANTE
  • 66.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 66 6 Les Exceptions 6.1 Erreurs et exceptions En C#, une exception est un objet de la classe System.Exception ou une de ses sous-classes. Les mots-clés utilisés pour traiter les exceptions sont : throw, catch, et finally. La gestion des exceptions requiert l’utilisation des mots-clés : - throw: Pour lancer ou relancer une exception. - try-catch: Pour capturer et traiter une exception. - try-finally: Pour libérer les ressources après le lancement de l’exception indépendamment de sa capture. - try-catch-finally: Pour capturer et traiter une exception et libérer les ressources. 6.2 Lancer une Exception throw [expression]; où: expression est l’exception. 6.3 Exemples d’exceptions : - InvalidCastException - OverFlowException - ArgumentNullException - ArithmeticException - DivideByZeroException Par exemple, l’appel à la méthode System.IO.File.OpenRead() peut provoquer le lancement des exceptions suivantes : - SecurityException - ArgumentException - ArgumentNullException - PathTooLongException - DirectoryNotFoundException - UnauthorizedAccessException - FileNotFoundException - NotSupportedException
  • 67.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 67 Exemple string monString = "Salut."; // Afficher la chaîne Console.Write("La chaîne est {0}", monString); monString = null; if (monString == null) { throw new ArgumentNullException(); // lancer l'exception } // Cette ligne n'est pas exécutée: Console.Write("monString est null."); 6.4 Capturer une Exception Pour capturer une exception, le code suspect est mis dans un bloc try : try {// Le code à protéger. } Le gestionnaire de l’erreur est mis dans un bloc de capture: catch [(declaration)] { // Le code du gestionnaire d’exception. } Où declaration est la déclaration de l’objet exception (optionnel). Exemple class MaClasse { public void MaMethode(string monString) { if (monString == null) // Lancer l'exception throw (new ArgumentNullException()); } public static void Main() { MaClasse MaClasse = new MaClasse(); // Le code suspect try { string monString = null; MaClasse.MaMethode(monString); } // Traitement de l'exception: catch (Exception e) { Console.WriteLine("L'exception suivante est capturée : n{0}", e); } // Continuer après le traitement de l'exception: Console.WriteLine("Le programme continue ..."); } }
  • 68.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 68 6.5 Organisation des gestionnaires Quand on utilise plus d'un bloc catch, il est important de capturer les exceptions spécifiques avant les moins spécifiques. Si un gestionnaire adéquat n’existe pas dans la méthode actuelle, le moteur d’exécution cherche dans les autres méthodes. Exemple: catch (ArithmeticException e) // premier gestionnaire { //... } ... ... catch (Exception e) // dernier gestionnaire { // ... } 6.6 Instruction try-finally L’utilisation du mot-clé finally permet d’introduire un code de nettoyage qui sera exécuté dans tous les cas. Cela permet, par exemple de libérer des ressources. try { // bloc-try } finally { // bloc-finally } Où : try-block : contient le code suspect à essayer finally-block : contient les instructions de ‘nettoyage’ à exécuter indépendamment de l'exception lancée. 6.7 Instruction try-catch-finally try { // bloc-try } catch { // bloc-catch } finally { // bloc-finally }
  • 69.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 69 6.8 Exceptions personnalisées On peut créer une exception personnalisée en la déclarant comme dérivée de ApplicationException. Avantage : personnaliser le texte du gestionnaire pour expliquer l’erreur. class MonExceptionPersonnalisee: ApplicationException Un constructeur avec un string comme paramètre est utilisé pour envoyer le message à la classe héritée: MonExceptionPersonnalisee(string message): base(message) { } Exemple // Une exception personnalisée public class MonException : Exception { // Constructeur de la classe MonException: public MonException(string message): base(message) { } } static void Main() { // Créer une instance de MonException: MonException e = new MonException("qui contient mon message personnalisé"); try { throw e; // Lancer l'exception } catch (MonException) { // Capturer l'exception: Console.WriteLine("L'exception {0} a été traitée avec succès.", e); } catch { Console.WriteLine("Exception inconnue traitée."); } finally { // Le code dans ce bloc est toujours exécuté: Console.WriteLine("Le programme continue ici."); } // Afficher un message après le bloc finally : Console.Write("Fin d'exécution."); }
  • 70.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 70 6.9 Relancer une exception Cela consiste à envoyer une exception à une autre méthode ou au Main pour avoir plus de détails. Pour cela on utilise throw sans paramètres: catch { throw; } Le bloc de capture peut ajouter un message. Exemple static void Main() { maClasse mc = new maClasse(); try { mc.MaMethode1(); // évènement #1 } catch (Exception e) { Console.WriteLine("Capturée dans le Main: {0}", e); // évènement #6 Console.WriteLine("On continue le nettoyage ..."); } } public void MaMethode1() { try { MaMethode2(); // évènement #2 } catch (Exception) { Console.WriteLine("Capturée dans MaMethode1"); // évènement #4 Console.WriteLine("Nettoyage ..."); // Relancer la même exception: throw; // évènement #5 } } public void MaMethode2() { throw new Exception("lancée par MaMethode2"); // évènement #3 } 6.10 Utilisation de StackTrace StackTrace permet de garder la trace de l’exception au fur et à mesure qu’elle est capturée. catch (Exception e) { Console.WriteLine("Capturée dans le Main: {0}", e.StackTrace); Console.WriteLine("On continue le nettoyage ..."); }
  • 71.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 71 6.11 Opérateur de condition null : ?. (C#6) Le code suivant { var exampleObject = new ExampleClass(); try { exampleObject.SomeMethod(); } finally { if (exampleObject != null) { exampleObject.Dispose(); } } } peut se réécrire en C#6 : { var exampleObject = new ExampleClass(); try { exampleObject.SomeMethod(); } finally { exampleObject?.Dispose(); } } 6.12 Filtres d’Exceptions (C#6) C# 6 a introduit des filtres d’exceptions qui permettent de capturer une basée sur un type et une condition qui spécifiée dans une clause ‘when’. catch(ExceptionType name) when(condition) ou encore dans une exception généralisée: catch when(condition) Exemple: try { Console.WriteLine("Filtres d'exception."); throw new Exception(); } catch (Exception ) when ( (DateTime.Now.DayOfWeek == DayOfWeek.Saturday) || (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)) { Console.WriteLine("Capturée."); }
  • 72.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 72 6.13 Nameof (C#6) Utilisé pour obtenir le nom d’une variable sous la forme d’un string. Ce qui peut être pratique dans la gestion des exceptions. Exemple : if (x == null) throw new ArgumentNullException(nameof(x)); WriteLine(nameof(personne.Addresse.CodePostal)); // affiche "CodePostal"
  • 73.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 73 7 Délégués et Événements 7.1 Définition d'un délégué Un délégué est un type (référence) qui permet de stocker des références à des fonctions. Il est utilisé pour encapsuler une méthode d'une signature spécifique et la passer en paramètre. Il est semblable à un pointeur de fonction en C++, sauf qu'il est de type sécurisé. Le délégué délègue la méthode associée pour réaliser son travail. Les délégués sont utiles pour la gestion des événements. Ils sont déclarés de manière similaire aux fonctions : • Mot-clé delegate, • Sans corps de fonction, • Un type de retour et une liste de paramètres. On peut déclarer une variable avec le type délégué. Cette variable sera initialisée comme une référence à toute fonction qui a le même type de retour et la même liste de paramètres que le délégué. On peut alors appeler cette fonction en utilisant la variable de type délégué comme s'il s'agissait d'une fonction. Les avantages de l’utilisation des délégués sont alors : • La possibilité de passer une variable de type délégué à une fonction comme paramètre, • la fonction peut utiliser le délégué pour appeler une fonction, quelle qu’elle soit, et sans la connaître avant l'exécution. Le mot-clé delegate offre la possibilité de créer des classes particulières, appelées "délégations", dont les instances sont nommées "délégués". 7.2 Déclaration des délégués Syntaxe : [modifiers] delegate result identifier ([parameters]) où: modifiers : est une combinaison valide de modificateurs d’accès plus le modificateur new. Result : est le type du délégué qui est le même que celui de la méthode encapsulée. Identifier : est le nom du délégué. Parameters : est une liste optionnelle de paramètres.
  • 74.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 74 Exemple: delegate void MonDelegue(object o1, object o2); Ce délégué peut encapsuler des méthodes avec la même signature : static void MaMethode(object o1, object o2) { ... } 7.3 Création du délégué La création se fait selon les étapes suivantes : 1. Déclarer le délégué (dans un namespace ou une classe). Par exemple: delegate void MonDelegue (object o1, object o2); 2. Déclarer la méthode qui lui sera associée. Exemple: public static void MaMethode(object id, object nom){…} Noter que les types de la valeur de retour et des paramètres sont identiques. 3. Créer un objet délégué : MonDelegue delegObj = new MonDelegue(MaMethode); Noter que le paramètre du délégué est le nom de la méthode encapsulée. On peut aussi créer un objet délégué sans utiliser new: MonDelegue delegObj = MaMethode; 7.4 Invocation du délégué On utilise les mêmes paramètres utilisés pour appeler la méthode associée. Exemple: delegObj(119, "Jane Doe"); Ou, à partir d’une méthode : public static void AppelDelegue (MonDelegue meth) { meth(119, "Jane Doe"); } On peut aussi utiliser la méthode .NET Invoke :
  • 75.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 75 delegObj.Invoke(119, "Jane Doe"); Exemple // Déclarer un délégué: delegate void MonDelegue(int n, string s); class MainClass { static void Main() { // Instancier la classe: MaClasse obj = new MaClasse(); // Instancier le delegué: MonDelegue d = new MonDelegue(obj.MaMethode); // Invoquer le delegue: obj.AppelDelegue(d); } } class MaClasse { // Une méthode pour invoquer le delegué: public void AppelDelegue(MonDelegue meth) { meth(119, "Jane Doe"); } // La méthode encapsulée : public void MaMethode(int id, string nom) { Console.WriteLine("ID = {0}nNom = {1}", id, nom); } } 7.5 Associer un délégué à plusieurs méthodes L’association entre un délégué et une méthode est réalisée dynamiquement lors de l’exécution. Le délégué ne sait pas lors de la compilation, quelle méthode il va encapsuler. Ce qui importe, c’est la signature et le type de retour de la méthode. On peut donc associer le même délégué avec plus d’une méthode dans un programme.
  • 76.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 76 Exemple public class Calc { // Declarer un délégué: public delegate double Calcul(int x, int y, int z); // Declarer les méthodes: public static double Somme(int n1, int n2, int n3) { return n1 + n2 + n3; } public static double Moyenne(int n1, int n2, int n3) { return (n1 + n2 + n3) / 3; } public static void Main() { double resultat; // Instancier le délégué, lui associer Moyenne : Calcul monCalc = new Calcul(Moyenne); // Invoquer le délégué: resultat = monCalc(3, 6, 9); Console.WriteLine("Moyenne: {0}", resultat); // Instancier un autre objet et l'associate à Somme : monCalc = new Calcul(Somme); // Invoquer le délégué: resultat = monCalc(3, 6, 9); Console.WriteLine("Somme: {0}", resultat); } } 7.6 Ajouter ou supprimer des délégués Les délégués peuvent être combinés en utilisant l’opérateur + pour créer un délégué composé. L’invocation de ce délégué va provoquer l’invocation de ses constituants. Le but de la composition est d’encapsuler plus d’une méthode dans le même délégué. Cette opération est le multicasting. On peut aussi supprimer un délégué d’une composition en utilisant le –. On peut utiliser += et –=. De manière similaire, on peut utiliser les méthodes .NET Combine et Remove qui sont membres de la classe System.delegate. Exemple
  • 77.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 77 // Déclarer un délégué: delegate void MonDelegue(); class MaClasse { public void MaMethode1() { Console.Write("MaMethode #1 "); } public void MaMethode2() { Console.Write("MaMethode #2 "); } } class MainClass { static void Main() { // Instancier MaClasse: MaClasse mc = new MaClasse(); // Déclarer un objet délégué et référencer MaMethode1: MonDelegue d1 = new MonDelegue(mc.MaMethode1); // Déclarer un objet délégué et référencer MaMethode2: MonDelegue d2 = new MonDelegue(mc.MaMethode2); // Déclarer le délégué d3 en additionnant d1 et d2. // Cela invoquera MaMethode1 et MaMethode2: MonDelegue d3 = d1 + d2; // Déclarer le délégué d4 en retirant d1 de d3. // Cela invoquera MaMethode2 uniquement: MonDelegue d4 = d3 - d1; Console.Write("Invoquer d1, référencer "); d1(); Console.Write("nInvoquer d2, référencer "); d2(); Console.Write("nInvoquer d3, référencer "); d3(); Console.WriteLine("nInvoquer d4, référencer "); d4(); } }
  • 78.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 78 7.7 Utiliser les méthodes .NET // Combiner d1 et d2, pour former d3: MonDelegue d3 = (MonDelegue) delegate.Combine(d1, d2); // enlever d1 de d3, pour donner d4: MonDelegue d4 = (MonDelegue) delegate.Remove(d3, d1); Quand on utilise les méthodes .NET, il est nécessaire d’utiliser un ‘cast’ pour convertir le résultat au type delegate. 7.8 Les événements L'une des utilisations les plus importantes des délégués est la programmation d'événements, notamment dans l'environnement Windows. Un clic sur un bouton déclenche un événement pour lequel la réponse à cet événement peut prendre plusieurs formes. Le programmeur doit écrire la réponse appropriée à cet événement. Un événement est reçu (réception) ou émis (émission). Plusieurs types d'évènements sont possibles : - Modifier du texte dans une zone de texte, - Passer à un autre contrôle, … La réception de l'événement dépend totalement de l'application en développement. 7.8.1 L'utilisation des événements On commence par déclarer un délégué à utiliser comme gestionnaire (ou récepteur) : delegate void RightButtonDown(object sender, EventArgs e); On utilise ensuite le nom du délégué (RightButtonDown) comme type de l’évènement déclaré avec le mot-clé event. Par exemple, pour appeler l’évènement PressDown, on le définit comme suit: event RightButtonDown PressDown; Le mot clé event protège l'accès au délégué de la manière suivante : • Il n'est plus possible d'utiliser l'affectation seule (opérateur =), il faut utiliser += ou -= ; • L'ajout et le retrait sont réalisés de manière synchrone, c-à-d que chaque évènement attend la fin du précédent pour s'exécuter. Si un évènement lance une exception, les suivants ne seront pas exécutés; • Il n'est pas possible d'appeler le delegate en dehors de la classe où l'event est déclaré.
  • 79.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 79 Exemple: class MonEventArgs : EventArgs { // Champs: private string stock; private int variation; // Propriétés: public string MonStock { get { return stock; } } public int MaVariation { get { return variation; } } // Constructeur: public MonEventArgs(string s, int c) { stock = s; variation = c; } } class Emetteur { public delegate void MonGestionnaire(object source, MonEventArgs e); public event MonGestionnaire Changement; // Mettre à jour le stock public void MettreAJour(string s, int c) { MonEventArgs e = new MonEventArgs(s, c); if (Changement != null) Changement(this, e); } } // Classe qui reçoit l'évènement class Recepteur { public Recepteur(Emetteur s) { // Ajouter l’évènement: s.Changement += new Emetteur.MonGestionnaire(OnStockChange); } void OnStockChange(object source, MonEventArgs e) { string plusOuMoins; if (e.MaVariation > 0) plusOuMoins = "moins"; else plusOuMoins = "plus"; int ch = Math.Abs(e.MaVariation); Console.WriteLine("{0} {1} {2}", e.MonStock, plusOuMoins, ch); } }
  • 80.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 80 // Classe principale class Program { public static void Main() { Emetteur s = new Emetteur(); Recepteur r = new Recepteur(s); // Afficher les résultats: Console.WriteLine("Ventes 2015:"); s.MettreAJour("tIntroduction à C#:", -20); s.MettreAJour("tLivres C++:", 11); s.MettreAJour("tLivres VB .NET:", -15); s.MettreAJour("tLivres de Science Fiction:", 120); } }
  • 81.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 81 8 Les Interfaces Une interface permet de déclarer le contenu de la classe qui l’implémente. C’est un contrat qui décrit le comportement de la classe qui implémente l’interface. Si l’interface contient le nom d’une méthode, la classe qui l’implémente est obligée de contenir l’implémentation de cette méthode. 8.1 Déclaration de l’interface interface IMonInterface { // membres de l’interface } La déclaration peut être modifiée par une combinaison valide de modificateurs d’accès ou par le mot-clé new. Elle peut aussi être précédée par des attributs. Les membres d’une interface peuvent être: • Des Méthodes • Des Propriétés • Des Indexeurs • Des Événements Cependant, l’interface ne peut pas contenir de champs. Les membres de l’interface sont publics par défaut et on ne peut pas utiliser de modificateurs d’accès sur les membres. 8.2 Membres Les membres d’une interface sont des signatures de méthodes, des propriétés, des indexeurs, ou des évènements. Par exemple: interface ICompteur { void Compter(int i); int SetCompteur(); } Une interface peut elle-même implémenter une ou plusieurs interfaces, comme dans l'exemple : interface IMonInterface: Interface1, Interface2 { // membres de l’interface }
  • 82.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 82 Dans cet exemple, IMonInterface implémente Interface1 et Interface2. 8.3 Implémentation de l’interface L'interface peut être implémentée par une classe ou une structure comme le montre cet exemple : class MaClasse:IMonInterface { // implémentation de la classe } Par cette déclaration, la classe MaClasse est tenue de mettre en œuvre tous les membres de l’interface IMonInterface. Une classe peut implémenter plus d'une interface: Une classe peut également implémenter une autre classe en plus des interfaces: class MaClasse: MaBaseClasse, IMonInterface1, IMonInterface2 { // implémentation de la classe } Exemple interface IPoint { // Propriétés : int MonX { get; set; } int MonY { get; set; } } class Point : IPoint { // Champs: private int x; private int y; // Constructeur: public Point(int x, int y) { this.x = x; this.y = y; } // implementation des propriétés : public int MonX
  • 83.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 83 { get { return x; } set { x = value; } } public int MonY { get { return y; } set { y = value; } } public static void AfficherMonPoint(IPoint monPoint) { Console.WriteLine("({0},{1})", monPoint.MonX, monPoint.MonY); } } class MaClasse { static void Main() { Point monPoint = new Point(12, 300); Console.Write("Mon point est créé avec les coordonnées: "); Point.AfficherMonPoint(monPoint); } } 8.4 Utiliser is pour tester les types Usage : expression is type où: type est une référence à un type Expression est l’objet à tester Le résultat est true ou false Exemple interface I1 { } interface I2 { } class Class1 : I1, I2 { } class MaClasse { static bool TesterType(object obj) { if (obj is I1 & obj is I2 & obj is Class1) return true; else return false;
  • 84.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 84 } public static void Main() { Class1 c = new Class1(); Console.WriteLine("Le résultat du test est: {0}", TesterType(c)); } } 8.5 Utiliser as pour convertir Convertir une expression à un type référence spécifié. Usage: expression as type où: type est une référence à un type, Expression est l’objet à convertir. Retourne la valeur de l’expression si la conversion réussit, null sinon. Ceci est équivalent à ‘caster’ expression avec type sauf qu’elle ne lance pas d’exception si la conversion échoue. Seules les références d’objets sont converties. Exemple : object o = "Chaîne de car dérive de la classe object" as object; Exemple complet public class MaClasse { static void TesterType(object o) { if (o as MaClasse != null) Console.WriteLine("L'objet "{0}" est une classe.", o); else if (o as string != null) Console.WriteLine("L'objet "{0}" est un string.", o); else Console.WriteLine("L'objet "{0}" n'est pas un type référence.", o); } static void Main() { MaClasse mc = new MaClasse(); string monString = "Bonjour le monde!"; int monInt = 123; TesterType(mc); TesterType(monString); TesterType(monInt); } 8.6 Cacher les membres d’une classe de base
  • 85.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 85 Soit la classe de base: public class MaBaseClass { public int monInt; public void MaMethode() // MaMethode dans la classe de base { // ...} } Pour utiliser le même nom d’un membre dans une classe héritée, on utilise new public class MaClasseDerivee: MaBaseClass { new public void MaMethode() // MaMethode de la classe dérivée { // ... Une méthode qui utilise le modificateur new, cache les propriétés et les champs qui ont le même nom. Elle cache aussi les méthodes avec les mêmes signatures. En général, déclarer un membre dans la classe héritée, cache tout membre de la classe de base qui porte le même nom. On ne peut pas utiliser new et override dans la même déclaration mais on peut utiliser new et virtual dans une même déclaration. Exemple : class BaseClasse { public virtual void Methode1() { Console.WriteLine("Base - Méthode1"); } public void Methode2() { Console.WriteLine("Base - Methode2"); } } class DeriveeClass : BaseClasse { public override void Methode1() { Console.WriteLine("Dérivée - Méthode1"); } public new void Methode2() // Masque methode2 de la
  • 86.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 86 { // classe de base. Il faut ajouter new Console.WriteLine("Dérivée - Méthode2"); } } class Program { static void Main(string[] args) { BaseClasse bc = new BaseClasse(); DeriveeClass dc = new DeriveeClass(); BaseClasse bcdc = new DeriveeClass(); bc.Methode1(); // Base - Méthode1 bc.Methode2(); // Base – Méthode2 dc.Methode1(); // Dérivée - Méthode1 dc.Methode2(); // Dérivée – Méthode2 bcdc.Methode1(); // Dérivée - Méthode1 bcdc.Methode2(); // Base – Méthode2 } } Le mot-clé new préserve la relation d’héritage. Les variables de type BaseClasse continuent à accéder aux membres de BaseClasse. Le mot-clé override permet à bcdc (de valeur de type DeriveeClasse) d’accéder à la méthode Methode1 qui est définie dans DeriveeClasse.
  • 87.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 87 9 L’interface Graphique (WinForms) 9.1 Contrôles La plupart des contrôles en .NET dérivent de la classe : System.Windows.Forms.Control qui définit les fonctionnalités de base des contrôles. Certaines classes sont elles-mêmes des classes de base pour d’autres contrôles. Exemples : classes Label et TextBoxBase 1. Les Propriétés Tous les contrôles ont un certain nombre de propriétés qui sont utilisées pour en manipuler le comportement. Exemples • Anchor: qui spécifie comment se comporte le contrôle quand la fenêtre est redimensionnée. • BackColor, ForeColor : Couleur d’arrière plan et d’avant plan du contrôle. • Bottom : distance à partir du haut de la fenêtre au bas du contrôle. • Dock : colle le contrôle au bord de son conteneur. • Enabled : à true, le contrôle peut recevoir des entrées de l’utilisateur. • Height: Hauteur du contrôle. • Name : nom du contrôle utilisé pour le référencer • Parent: Le parent du contrôle. • TabIndex: Numéro du contrôle. • TabStop: Indique si le contrôle peut être accédé par la touche Tab.
  • 88.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 88 • Text: Texte associé avec le contrôle. • Visible: Indique si le contrôle est visible lors de l’exécution. • Width: Largeur du contrôle. 2.2.2.2. Les événements Voici quelques événements générés par les contrôles : • Click, DoubleClick: L’utilisateur clique sur le contrôle ou appuie sur Enter, • DragDrop: Une opération ‘drag - and – drop’ est terminée et l’utilisateur lâche le bouton de la souris. • DragEnter: un objet tiré entre dans les limites du contrôle. (DragLeave, DragOver). • KeyDown: une touche est activée quand le contrôle a le focus. Se produit toujours avant KeyPress et KeyUp. • KeyPress: Une touche est activée quand le contrôle a le focus (après KeyDown et avant KeyUp). • KeyUp: Une touche est relâchée quand le contrôle a le focus (après KeyDown et KeyPress). • GotFocus, LostFocus: Un contrôle reçoit ou perd le focus. • MouseDown: La souris est sur le contrôle et l’utilisateur appuie sur un bouton. (différent de Click car il intervient avant que le bouton est relâché). • MouseMove: En continu quand la souris traverse le contrôle. • MouseUp: Le pointeur de la souris est sur un contrôle et un bouton est relâché. • Validated: Un contrôle avec la propriété CausesValidation à true va recevoir le focus. Intervient après que l’évènement validant se termine et indique que la validation est achevée. Il existe trois méthodes de base pour gérer un événement particulier. • Double-cliquer sur un contrôle, ce qui amène au gestionnaire d'événement pour le contrôle de l’événement par défaut (différent pour chaque contrôle). • Si événement autre que celui par défaut: - Utiliser la liste des événements dans la fenêtre Propriétés, - Ajouter soi-même le code à associer à l'événement.
  • 89.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 89 9.2 Boutons Voici un exemple simple d’utilisation des boutons: Pour créer cet exemple il faut : - Tirer 3 fois le contrôle Button de la boîte à outils de Visual Studio, - Changer la propriété name de chaque bouton pour le renommer, - A chaque bouton associer le code approprié (double cliquer sur un bouton pour accéder à son code). Voici, par exemple, le code associé au bouton English private void buttonEnglish_Click(object sender, EventArgs e) { this.Text = “Do you speak English?”; } private void buttonOK_Click(object sender, EventArgs e) { Application.Exit(); } 9.3 Les étiquettes (Label) Il existe deux contrôles d'étiquette qui se présentent sous deux formes distinctes: - Label qui est l’étiquette standard, et - LinkLabel qui est une étiquette semblable à la précédent mais qui se présente comme un lien hypertexte.
  • 90.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 90 9.4 Boîte de texte Une boîte de texte est utilisée pour entrer du texte ou un nombre. Il existe dans cette catégorie deux contrôles de base : - TextBox - RichTextBox. Les deux sont dérivés de la classe de base : TextBoxBase. Exemple Dans cet exemple : - La propriété Scrollbars des contrôles txtOutput et txtAddress est mise à Vertical. - La propriété ReadOnly du contrôle txtOutput est à true. - La propriété CausesValidation du bouton btnHelp est à false. Cela permet aux utilisateurs de cliquer sur ce bouton sans avoir à se soucier d'entrer des données invalides. Voici le code associé à chacun des boutons : private void buttonOK_Click(object sender, EventArgs e) { // Pas de test des valeurs invalides string output; // Concatene le texte des 4 TextBox.
  • 91.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 91 output = “Nom: “ + this.textBoxName.Text + “rn”; output += “Adresse: “ + this.textBoxAddress.Text + “rn”; output += “Fonction: “ + this.textBoxOccupation.Text + “rn”; output += “Age: “ + this.textBoxAge.Text; // Insère le nouveau texte. this.textBoxOutput.Text = output; } private void buttonHelp_Click(object sender, EventArgs e) { string output; output = “Nom = Votre nom rn”; output += “Adresse = Votre adressern”; output += “fonction = Seule valeur possible : Programmeur’rn”; output += “Age = Votre âge”; // Insère le nouveau texte. this.textBoxOutput.Text = output; } 9.5 Les contrôles RadioButton et CheckBox Ces contrôles permettent d’insérer des boutons radios ou des cases à cocher. Exemple :
  • 92.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 92 Dans cet exemple : - La propriété checked de la case à cocher checkBoxProgrammer est à true. - La propriété Checked de radioButtonMale ou deradioButtonFemale est à true. 9.6 Le contrôle RichTextBox Ce contrôle est utilisé pour afficher et entrer du texte formaté (par exemple, gras, souligné et en italique). Il utilise le format RTF (Rich Text Format). Exemple :
  • 93.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 93 Voici le code associé aux boutons de cet exemple :
  • 94.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 94 9.7 Les contrôles ListBox et CheckedListBox Les zones de liste sont utilisées pour afficher une liste de string à partir de laquelle un ou plusieurs éléments peuvent être sélectionnés à la fois. Cette zone de liste permet aux utilisateurs de faire une ou plusieurs sélections. Le contrôle CheckedListBox fournit une liste, mais en plus du texte, il fournit une marque qui permet de vérifier chaque élément dans la liste. Exemple Voici le code associé à cet exemple : public Form1() { InitializeComponent(); // Ajouter un element à la CheckedListBox. this.checkedListBoxPossibleValue.Items.Add(“Ten”); } private void buttonMove_Click(object sender, EventArgs e) { if(this.checkedListBoxPossibleValue.CheckedItems.Count>0) { this.listBoxSelected.Items.Clear(); foreach (string item in this.checkedListBoxPossibleValue.CheckedItems) { this.listBoxSelected.Items.Add(item.ToString()); } for (int i=0;i<this.checkedListBoxPossibleValue.Items.Count; i++)
  • 95.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 95 this.checkedListBoxPossibleValue.SetItemChecked(i, false); } } 9.8 Menus Visual Studio offre 2 types de contrôles pour créer facilement des menus déroulants: - Pour créer un menu normal on utilise le contrôle MenuStrip - Pour un menu contextuel on utilise le contrôle ContextMenuStrip . Voilà le texte à saisir pour créer le menu ci-contre &New &Open - &Save Save &As - &Print Print Preview - E&xit
  • 96.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 96 10 Introduction à Windows Presentation Foundation 10.1 Introduction WPF représente la nouvelle génération d’interfaces utilisateur de Microsoft. Il permet de créer des applications graphiques riches. Il fait partie du framework .NET 3.0 et plus. WPF combine les applications d’interfaces utilisateur, le graphisme 2D, le graphisme 3D, les documents et le multimédia dans un même framework. C’est une UI plus rapide, évolutive et indépendante de la résolution d’écran. 10.2 Principales caractéristiques de WPF • Séparation de l’apparence et du comportement WPF sépare l’apparence de l’interface de son comportement (code). L’apparence est généralement spécifiée en Extensible Application Markup Language (XAML), le comportement est implémenté en C# ou Visual Basic. • Compositions riches Les contrôles WPF sont extrêmement composables. N’importe quel type de contrôle peut être défini comme le contenu d’un autre contrôle. <Button> <StackPanel Orientation="Horizontal"> <Image Source="speaker.png" Stretch="Uniform"/> <TextBlock Text="Play Sound" /> </StackPanel> </Button>
  • 97.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 97 • Personnalisation extrême Grâce à la stricte séparation de l’apparence du code, il est très facile de changer le look d’un contrôle. Le concept de styles permet d’habiller les contrôles comme avec CSS en HTML. Les gabarits (Templates) permettent d’en remplacer toute l’apparence. Voilà un exemple de bouton standard puis personnalisé. • Indépendance de la résolution Les mesures dans WPF sont des unités logiques et non des pixels. Une unité logique est un 1/96 d'un pouce. Quand on augmente la résolution de l’écran, l'interface reste de la même taille - cela devient juste plus précis. WPF est construit sur un moteur de rendu vectoriel ce qui rend très facile de construire des interfaces scalables. 10.3 Créer une application WPF simple Ouvrir Visual Studio et choisir un projet du type "WPF Application». La structure du projet ressemble à WinForms, sauf que le fichier Window1.designer.cs n’est plus du code mais du XAML déclaré dans MainWindow.xaml
  • 98.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 98 Ouvrez le fichier MainWindow.xaml dans le concepteur WPF et ajoutez un Bouton et une TextBox. Changez le texte du bouton. Double-cliquez sur le bouton et ajoutez-lui le code : private void button1_Click(object sender, RoutedEventArgs e) { txtBonjour1.Text = "Bonjour WPF!"; } Testez votre application.
  • 99.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 99 10.4 Contrôle TextBox Activer la correction orthographique TextBox et RichTextBox permettent la correction orthographique pour les langages : anglais, espagnol, allemand et français. On l’active en mettant la propriété SpellCheck.IsEnabled à true. <TextBox SpellCheck.IsEnabled="True" Language="en-US" /> Valider l’entrée en utilisant les expressions régulières : protected override void OnTextInput(TextCompositionEventArgs e) { string fullText = Text.Remove(SelectionStart, SelectionLength) + e.Text; if (_regex != null && !_regex.IsMatch(fullText)) { e.Handled = true; } else { base.OnTextInput(e); } }
  • 100.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 100 10.5 Contrôle Bouton Radio Pour grouper des RadioButtons on met la propriété GroupName au même nom. Pour préselectionner une option on met sa propriété IsChecked à True. <StackPanel> <RadioButton GroupName="Os" Content="Windows 7" IsChecked="True"/> <RadioButton GroupName="Os" Content="Windows 8.1" /> <RadioButton GroupName="Os" Content="Windows 10" /> <RadioButton GroupName="Office" Content="Microsoft Office 2010" IsChecked="True"/> <RadioButton GroupName="Office" Content="Microsoft Office 2013"/> <RadioButton GroupName="Office" Content="Open Office"/> </StackPanel> Contrôle ListBox Code XAML: <ListBox Margin="20"> <ListBoxItem>New York</ListBoxItem> <ListBoxItem>Los Angeles</ListBoxItem> <ListBoxItem>Paris</ListBoxItem> <ListBoxItem>Zürich</ListBoxItem> </ListBox>
  • 101.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 101 10.6 Ajouter supprimer dynamiquement un élément •••• Ajouter une TextBox et un bouton ‘Ajouter’. Associer au bouton le code : private void button1_Click(object sender, RoutedEventArgs e) { listBox1.Items.Add(textBox1.Text); } •••• Ajoutez un bouton ‘Supprimer’ et lui associer le code private void DeleteButton_Click(object sender, RoutedEventArgs e) { listBox1.Items.RemoveAt (listBox1.Items.IndexOf(listBox1.SelectedItem)); } 10.7 Créer un Menu <Menu IsMainMenu="True"> <MenuItem Header="_File" /> <MenuItem Header="_Edit" /> <MenuItem Header="_View" /> <MenuItem Header="_Window" /> <MenuItem Header="_Help" /> </Menu> •••• Les MenuItem Le contenu de Header est l’affichage du menu. Les Items sont les sous-menus. La propriété Icon permet de rajouter un second contenu (une image) à la gauche de l’affichage. On peut definir un raccourci clavier en ajoutant un underscore devant le caractère. <MenuItem Header="_Edit"> <MenuItem Header="_Cut" Command="Cut"> <MenuItem.Icon> <Image Source="Images/cut.png" /> </MenuItem.Icon> </MenuItem> <MenuItem Header="_Copy" Command="Copy">
  • 102.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 102 <MenuItem.Icon> <Image Source="Images/copy.png" /> </MenuItem.Icon> </MenuItem> <MenuItem Header="_Paste" Command="Paste"> <MenuItem.Icon> <Image Source="Images/paste.png" /> </MenuItem.Icon> </MenuItem> </MenuItem> •••• Menus Contextuels en WPF Les Menus Contextuels peuvent être definis sur n’importe quel contrôle WPF en associant sa propriété ContextMenu à une instance de ContextMenu. Les éléments du menu contextual sont des MenuItems classiques. <RichTextBox> <RichTextBox.ContextMenu> <ContextMenu> <MenuItem Command="Cut"> <MenuItem.Icon> <Image Source="Images/cut.png" /> </MenuItem.Icon> </MenuItem> <MenuItem Command="Copy"> <MenuItem.Icon> <Image Source="Images/copy.png" /> </MenuItem.Icon> </MenuItem> <MenuItem Command="Paste"> <MenuItem.Icon> <Image Source="Images/paste.png" /> </MenuItem.Icon> </MenuItem> </ContextMenu> </RichTextBox.ContextMenu> </RichTextBox> Ouvrir un menu contextuel à partir du code
  • 103.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 103 Exemple: private void OpenContextMenu(FrameworkElement element) { if( element.ContextMenu != null ) { element.ContextMenu.PlacementTarget = element; element.ContextMenu.IsOpen = true; } }
  • 104.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 104 11 Collections et itérateurs - Génériques Il existe diverses classes pour stocker des collections d'éléments en plus des tableaux. Ces collections ont été introduites pour pallier aux différents inconvénients des tableaux (statiques de taille fixe). Ces collections sont soit sous la forme non-générique, c-à-d dédiées à un type particulier, ou génériques. Elles sont définies dans les espaces de noms : System.Collections et System.Collections.Generic Dans la suite, et comme illustration des collections non génériques, nous présentons la collection ArrayList et deux collections génériques fréquemment utilisées : la liste et le dictionnaire. 11.1 Exemples de collections Voici quelques exemples de collections qui ne seront (malheureusement) pas toutes présentées dans ce support de cours :  La collection Stack : Classe LIFO qui représente une PILE (dernier entré premier servi).  La collection Queue : Classe FIFO qui représente une FILE (premier entré premier servi).  La collection ArrayList : qui représente un tableau dynamique non trié  La collection SortedList : similaire à ArrayList mais trié sur une clé  La collection Hashtable : Collection d'entrées clé/valeur. Les entrées sont triées selon le code de hachage de la clé.  La collection Linked List : qui représente une liste linéaire doublement chaînée 11.2 La classe non générique ArrayList ArrayList est capable de stocker des références sur des objets quelconques. Un objet ArrayList ressemble à ceci : Les éléments 0, 1 et i de la liste pointent sur des objets de types différents. Bien entendu, Il faut qu'un objet soit d'abord créé avant d'ajouter sa référence à la liste ArrayList.
  • 105.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 105 Bien qu'un ArrayList stocke des références d'objet, il est possible d'y stocker des nombres par utilisation du Boxing. Exemple : ArrayList liste=new ArrayList(); liste.Add(4); // récupérer le nombre : Unboxing int i = (int)liste[0]; Les méthodes disponibles sont: add, insert, clone, contains, getEnumerator, reverse, sort, … Exemple d’ArrayList static void Main(string[] args) { // Créer une ArrayList: ArrayList monArrayList = new ArrayList(); // Afficher la capacité initiale Console.WriteLine("La capacité initiale est : {0}", monArrayList.Capacity); // Initialiser la liste avec des éléments: monArrayList.Add("SNL"); monArrayList.Add("Mad TV"); monArrayList.Add("Seinfeld"); monArrayList.Add("Everybody Loves Raymond"); monArrayList.Add("Married with Children"); // Afficher le nombre d'éléments Console.WriteLine("The number of items: {0}", monArrayList.Count); // Afficher la nouvelle capacité: Console.WriteLine("La capacité est maintenant : {0}", monArrayList.Capacity); // Afficher les éléments de la liste Console.WriteLine("nLe contenu de l'ArrayList: "); DisplayIt(monArrayList); // Trier et afficher la liste monArrayList.Sort(); Console.WriteLine("nLe contenu de l'ArrayList triée: "); DisplayIt(monArrayList); } public static void DisplayIt(ArrayList maListe) { foreach (object item in maListe) Console.WriteLine("{0}", item); }
  • 106.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 106 11.3 Utilisation des énumérateurs Les énumérateurs permettent de parcourir une collection. Ils sont uniquement utilisés pour lire des données et ne peuvent pas modifier la collection. On les crée en implémentant les interfaces IEnumerable et IEnumerator : IEnumerator contient 2 méthodes abstraites, MoveNext et Reset, et une propriété Current. object Current {get;} bool MoveNext() void Reset() Ces méthodes permettent de parcourir les collections en utilisant une boucle foreach. Ce qui est recommandé car cela cache la complexité des énumérateurs. 11.3.1 IEnumerator L’implémentation de cette interface permet de lire la collection. Pour cela : – Appeler MoveNext pour aller sur le premier élément de la collection, – Puis utiliser Current pour lire les éléments. – Chaque lecture suivante doit être précédée de MoveNext. Si l’énumérateur est avant le premier élément ou après le dernier, MoveNext retourne false et la valeur de Current devient indéfinie. Exemple // Declarer la collection: public class MaCollection : IEnumerable { string[] items; public MaCollection() { items = new string[4] { "Ceci", "est", "ma", "collection." }; } // Implementer la méthode GetEnumerator() : IEnumerator IEnumerable.GetEnumerator() { return new MonEnumerator(this); } // Implementer les membres de IEnumerator: public class MonEnumerator : IEnumerator { int pointeur; MaCollection maColl; public MonEnumerator(MaCollection c) { maColl = c; pointeur = -1; }
  • 107.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 107 // Implementer Reset: public void Reset() { pointeur = -1; } // Implementer MoveNext: public bool MoveNext() { pointeur++; if (pointeur > maColl.items.Length - 1) return false; return true; } // Implementer la propriété Current dans IEnumerator: object IEnumerator.Current { get { return (maColl.items[pointeur]); } } } } class maClass { public static void Main(string[] args) { MaCollection maColl = new MaCollection(); // Display the collection: foreach (string item in maColl) { Console.Write(item + " "); } Console.WriteLine(); } } Autre exemple : nouvelle version de l’exemple précédent qui utilise un énumérateur basé sur l’interface IDictionaryEnumerator. public class LDClasse { public static void Main(string[] args) { // Créer un objet ListDictionary vide ListDictionary monLD = new ListDictionary(); // Initialiser la collection ListDictionary . monLD.Add("Learn Pascal", "$39.95"); monLD.Add("Learn Pascal in Three Days", "$19.95"); monLD.Add("Learn C in Three Days", "$19.95"); monLD.Add("Learn J#", "$35.95"); monLD.Add("Learn C#", "$39.95"); // Afficher le contenu de la collection: DisplayIt(monLD); }
  • 108.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 108 // Afficher le contenu en utilisant un énumerateur: public static void DisplayIt(IDictionary maLD) { IDictionaryEnumerator monEnumerateur = maLD.GetEnumerator(); string s = "tttt"; Console.WriteLine("Livre{0}Prixn", s); while (monEnumerateur.MoveNext()) Console.WriteLine("{0,-32}{1}", monEnumerateur.Key, monEnumerateur.Value); } } 11.4 Itérateurs L'application de l’interface IEnumerator peut être difficile, surtout avec des énumérations complexes. C # 2005 a introduit les itérateurs pour résoudre le problème de cette complexité. Un itérateur est utilisé pour parcourir une collection et retourner une séquence de valeurs du même type. L'épine dorsale de l’itérateur est le mot-clé yield qui spécifie la valeur retournée. Pour créer un itérateur il faut implémenter la méthode GetEnumerator de l'interface IEnumerable: class MaClasse { public string[] item = {"One", "Two", Three"}; public IEnumerator GetEnumerator() { for (int i = 0; i < item.Length; i++) yield return item[i]; } } La présence de la méthode GetEnumerator rend la classe énumérable ce qui permet d’utiliser la boucle foreach : MaClasse mc = new MaClasse(); foreach (string item in mc) { Console.WriteLine(item); }
  • 109.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 109 11.4.1 L’instruction yield yield return expression; Cette instruction est utilisée pour itérer une collection. Elle est utilisée pour évaluer et retourner expression, qui est la valeur de l'objet itérateur. Cette instruction retourne la propriété Current de l’élément. L’instruction yield break; est utilisée pour terminer l'énumération. Il est possible d'utiliser plus d'une déclaration yield return dans un même itérateur pour retourner plusieurs valeurs comme dans l’exemple suivant : public class MaClasse { public IEnumerable MonIterator() { yield return "Bonjour!"; yield return "Je suis votre itérateur."; yield return "Je peux retourner"; yield return "autant d'éléments que nécessaire."; } public static void Main() { MaClasse mc = new MaClasse(); foreach (string item in mc.MonIterator()) Console.Write(item + " "); } } 11.5 Les collections génériques C’est une fonctionnalité permettant au programmeur de concevoir des classes ou des membres de fonction tout en reportant la définition du type à l’instanciation de la classe. Sans génériques, si on a besoin d'une pile d'entiers et d’une pile de chaînes de caractères, on doit créer une collection pour chaque type. Avec les génériques, on peut créer une collection générique utile pour tous les types, et reporter la spécification du type réel au moment de la création des objets. On utilise l'espace de noms System.Collections.Generic.
  • 110.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 110 11.5.1 Exemples de classes génériques List<T> Stack<T> Dictionary<TKey, TValue> LinkedList<T> Exemple d’utilisation de la collection générique Stack : Stack<double> maPile = new Stack<double>(); Stack<int> maPile = new Stack<int>(); Stack<string> maPile = new Stack<string>(); On détermine le type lors de l’instanciation de la classe Stack. La syntaxe de la classe générique Stack est : public class Stack<T> { } La lettre T, est appelée type du paramètre, est remplacée lors de l’instanciation par type argument, qui est n’importe quel type (int, double, …). On peut créer des types, des méthodes, des propriétés, des délégués, et des interfaces génériques. 11.5.2 La classe générique List<T> La classe System.Collections.Generic.List<T> permet d'implémenter des collections d'objets de type T dont la taille varie au cours de l'exécution du programme. Un objet de type List<T> se manipule presque comme un tableau: l'élément i d'une liste l est noté l[i]. List<T> implémente les interfaces génériques IList<T>, ICollection<T> et IEnumerable<T> et les interfaces non-génériques IList, ICollection et IEnumerable. Il est à noter que ArrayList est fonctionnellement équivalente à List<Object>. Si une liste est entièrement composée de types int, la déclarer comme List<int> améliore les performances: les nombres de type int sont stockés dans la liste elle-même et non dans des types Object extérieurs à la liste. Il n’est donc pas nécessaire de recourir au Boxing/Unboxing. Pour un objet List<T> où T est une classe, la liste stocke là encore les références des objets de type T.
  • 111.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 111 11.5.2.1Propriétés de List<T> – public int Count {get;} // qui donne le nombre d'éléments de la liste – public int Capacity {get;} // qui donne le nombre d'éléments que la liste peut contenir avant d'être redimensionnée. Le redimensionnement se fait automatiquement. 11.5.2.2Méthodes des listes génériques – public void Add(T item) : ajoute item à la liste. – public int BinarySearch<T>(T item) : retourne la position de item dans la liste s'il s'y trouve sinon un nombre <0. – public int BinarySearch<T>(T item, IComparer<T> comparateur) : idem mais le 2ième paramètre permet de comparer deux éléments de la liste. Utilise l'interface IComparer<T>. – public void Clear() : supprime tous les éléments de la liste. – public bool Contains(T item) : retourne True si item est dans la liste. – public void CopyTo(T[] tableau) : copie les éléments de la liste dans tableau. – public int IndexOf(T item): retourne la position de item dans tableau ou -1 si non trouvé. – public void Insert(T item, int index) : insère item à la position index. – public bool Remove(T item): supprime item de la liste. La méthode retourne True si l'opération réussit, False sinon. – public void RemoveAt(int index) : supprime l'élément n° index de la liste. – public void Sort(IComparer<T> comparateur) : trie la liste selon un ordre défini par comparateur. – public void Sort() : trie la liste selon l'ordre défini par le type des éléments de la liste. – public T[] ToArray() : retourne les éléments de la liste sous forme de tableau Exemple static void Main(string[] args) { // Déclarer la liste: List<string> maListe = new List<string>(); // Construire la liste: maListe.Add("Dylan"); maListe.Add("Isabella"); maListe.Add("Eve"); maListe.Add("Angelina"); // Afficher les éléments: DisplayIt(maListe); // Ajouter un nouvel élément: maListe.Insert(3, "Bill"); Console.WriteLine("Adding Bill..."); // Afficher les éléments: DisplayIt(maListe);
  • 112.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 112 // Rechercher l'élément "Bill" dans la liste: bool test = maListe.Contains("Bill"); Console.WriteLine("Est-ce que "Bill" est dans la liste? {0}", test); // Enlever "Bill" et le rechercher à nouveau: maListe.Remove("Bill"); Console.WriteLine("Enlever Bill..."); test = maListe.Contains("Bill"); Console.WriteLine("Est-ce que "Bill" est dans la liste? {0}", test); Console.WriteLine(); // Afficher les éléments: DisplayIt(maListe); // Afficher l'élément #2: Console.WriteLine("Élément numéro 2: {0}", maListe[2]); } // Afficher la liste: static void DisplayIt(List<string> maL) { foreach (string nom in maL) { Console.WriteLine(nom); } Console.WriteLine(); } 11.5.3 La classe Dictionary<TKey,TValue> Cette classe permet d'implémenter un dictionnaire. On peut voir un dictionnaire comme un tableau à deux colonnes : Les clés sont de type Tkey et les valeurs de type TValue. Les clés sont uniques. La valeur associée à la clé C d'un dictionnaire D est obtenue par la notation D[C]. Cette valeur est en lecture et écriture. Exemple: TValue v=...; TKey c=...; Dictionary<TKey,TValue> D = new Dictionary<TKey,TValue>(); D[c]=v; v=D[c]; Si la clé c n'existe pas dans le dictionnaire D, la notation D[c] lance une exception. La classe Dictionary implémente les interfaces génériques :  IDictionary<TKey, TValue>
  • 113.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 113  ICollection<KeyValuePair<TKey, TValue>>  IEnumerable<KeyValuePair<TKey, TValue>> Et les interfaces non-génériques :  IDictionary  ICollection  IEnumerable  ISerializable  IDeserializationCallback 11.5.3.1 Constructeurs et Propriétés Constructeurs – public Dictionary<TKey,TValue>() : est un constructeur sans paramètres qui construit un dictionnaire vide. – public Dictionary(int capacity) – public Dictionary(IDictionary<Tkey,TValue> dictionary) Propriétés – public int Count {get;} : nombre d'entrées (clé, valeur) dans le dictionnaire – public Dictionary<TKey,TValue>.KeyCollection Keys {get;} :qui retourne la collection des clés du dictionnaire. – public Dictionary<TKey,TValue>.ValueCollection Values {get;}: retourne la collection des valeurs du dictionnaire. Méthodes – public void Add(TKey key, TValue value) : ajoute le couple (key, value) au dictionnaire. – public void Clear() : supprime tous les couples du dictionnaire. – public bool ContainsKey (TKey key) : retourne True si key est une clé du dictionnaire, False sinon. – public bool ContainsValue (TValue value) : retourne True si value est une valeur du dictionnaire, False sinon. – public void CopyTo(T[] tableau) : méthode qui copie les éléments de la liste dans tableau. – public bool Remove(TKey key) : méthode qui supprime du dictionnaire le couple de clé key. Cette méthode retourne True si l'opération réussit, False sinon. – public bool TryGetValue(TKey key,out TValue value): retourne dans value, la valeur associée à la clé key si cette dernière existe, sinon rend la valeur par défaut du type TValue (0 pour les nombres, false pour les booléens, null pour les références d'objet)
  • 114.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 114 Exemple public static void Main() { // Créer une collection Dictionary vide Dictionary<string, double> monDictionnaire = new Dictionary<string, double>(); // Ajouetr des éléments au dictionnaire // On assume que les clés sont les fruits et les valeurs les prix. // Les prix peuvent être dupliqués. monDictionnaire.Add("Pommes", 0.30); monDictionnaire.Add("Oranges", 0.50); monDictionnaire.Add("Cerises", 0.44); monDictionnaire.Add("Pêches", 0.50); // Afficher le éléments en utilisant les paires Clé/Valeur : foreach (KeyValuePair<string, double> mD in monDictionnaire) { Console.WriteLine("{0,-20}{1:C}", mD.Key, mD.Value); } // Chercher les cerises et afficher le prix: ChercherElement(monDictionnaire, "Cerises"); // Chercher les "Oranges," et afficher le prix: ChercherElement(monDictionnaire, "Oranges"); // Enlever les "Oranges": monDictionnaire.Remove("Oranges"); Console.WriteLine("Oranges enlevées..."); // Chercher les "Oranges," et afficher le prix: ChercherElement(monDictionnaire, "Oranges"); } // Une méthode pour rechercher une clé spécifique dans le Dictionnaire: static void ChercherElement(Dictionary<string, double> monDictionnaire, string s) { if (monDictionnaire.ContainsKey(s)) Console.WriteLine("{0} sont en magasin. Le prix est {1:C}.", s, monDictionnaire[s]); else Console.WriteLine("{0} ne sont pas en magasin. SVP revenez plus tard.", s); }
  • 115.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 115 12 ADO.NET 12.1. SQL Server et Visual Studio La version Express de Visual Studio est livrée avec SQL Server Compact 3.5. Cet SGBD léger ne sait gérer qu'un utilisateur à la fois, mais il suffisant pour introduire la programmation avec les bases de données. Nous présentons ci-après quelques concepts nécessaires à l’exploitation d’une base de données dans Visual Studio. 1.1 Configurer la Base de Données Pour utiliser une BD existante on suit les étapes ci-après: - Afficher l’explorateur de serveurs, - Cliquer avec le bouton droit sur le nœud Connections de données, - Entrer localhost comme nom de serveur, - Cliquer sur « Tester la Connexion » - Choisir la DB (Sélectionner ou Entrer un nom de base de données). Pour créer une nouvelle BD, on fait: - Afficher l’explorateur de serveurs, - Créer une nouvelle base de données SQL Server 11.1.2 Créer une table Pour créer une table : - Ouvrir l’onglet de la BD et - faire un clic droit sur tables puis - Ajouter table - Rentrer les colonnes de la table - Dans le script en bas de la fenêtre, choisir le nom de la table puis faire ‘Mettre à jour’.
  • 116.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 116 1.2 SQL : Rappels - Instruction SELECT Permet de réaliser une sélection de lignes dans une ou plusieurs tables. Sa syntaxe est la suivante : SELECT [colonnes] FROM [tables] WHERE [condition] ORDER BY [expression ASC | DESC] Exemples (sur la BD PUBS de Microsoft): •••• SELECT * FROM Authors •••• SELECT lname, fname FROM Authors WHERE State='CA' ORDER BY lname ASC •••• SELECT TOP 100 * FROM Sales ORDER BY ord_date DESC •••• SELECT * FROM Sales WHERE ord_date < '2000/01/01' AND ord_date > '1987/01/01‘ •••• SELECT * FROM Stores WHERE stor_name LIKE '%book%‘ •••• SELECT COUNT(*) FROM Authors •••• SELECT SUM(qty) FROM Sales - Instruction UPDATE: L’instruction UPDATE sélectionne tous les enregistrements qui correspondent à une expression et les modifie selon l’expression spécifiée dans le UPDATE. Sa syntaxe est : UPDATE [table] SET [expression] WHERE [condition] Exemples: - UPDATE Authors SET phone='408 496-2222' WHERE id='172-32-1176‘ - UPDATE Authors SET lname='Whiteson', fname='John‘ WHERE lname='White' AND fname='Johnson‘ - UPDATE Titles SET price=price+1 WHERE pubdate >= '1991/01/01' AND pubdate < '1992/01/01' - Instruction INSERT L’instruction INSERT permet d’ajouter une ligne à une table. La syntaxe est : INSERT INTO [table] ([liste_colonnes]) VALUES ([liste_valeurs])
  • 117.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 117 Exemple INSERT INTO Authors (id, lname, fname, zip, contract) VALUES ('998-72-3566', 'Khan', 'John', 84152, 0) - Instruction DELETE: L’instruction DELETE permet de supprimer des lignes dans une table. Sa syntaxe est : DELETE FROM [table] WHERE [condition] Exemple: DELETE FROM Authors WHERE id='172-32-1176' - Les fonctions d’agrégation sont données par le tableau suivant : 12.2. Les Bases de ADO.NET ADO.NET est un petit ensemble de classes de base qui sont de 2 types: - Les classes pour contenir et gérer les données (DataSet, DataTable, DataRow et DataRelation). Ces classes sont génériques et toutes les données sont stockées dans un DataSet (voir infra). - Les classes pour se connecter à une source de données spécifique (Connection, Command et DataReader). Il existe plusieurs types de fournisseurs de données ADO.NET (data provider ) qui sont optimisés pour améliorer l'interaction avec la source de données.
  • 118.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 118 Exemples de fournisseurs: • SQL Server provider pour l’accès à SQL Server • OLE DB provider pour l’accès à n’importe quelle source qui a un driver OLE DB (Object Linking and Embedding, Database) • Oracle provider: accès à une BD Oracle (version 8i ou plus) • ODBC provider: accès à n’importe quelle source qui a un driver ODBC (Open Database Connectivity). Les connecteurs ODBC présentent une interface standard aux applications qui les utilisent et qui peuvent ainsi dialoguer avec tout SGBD ayant un connecteur ODBC. Les performances des connecteurs ODBC sont moins bonnes que celles des connecteurs "propriétaires" qui savent exploiter toutes les caractéristiques d'un SGBD particulier. En contre-partie, on obtient une grande souplesse de l'application. Les pilotes OLE DB sont similaires aux pilotes ODBC. Alors que les pilotes ODBC permettent l'accès à des bases de données, les sources de données pour les pilotes OLE DB sont plus variées: bases de données, messageries, annuaires, ... 1. Espaces de noms ADO pour Microsoft SQL Server L’espace de noms System.Data contient des classes ADO.NET fondamentales qui proposent les fonctionnalités de base. Exemples: DataSet et DataRelation, qui permettent de manipuler des données relationnelles. Ces classes sont totalement indépendantes de tout type spécifique de base de données ou de la façon de s’y connecter. L’espace de noms System.Data.SqlClient contient les classes à utiliser pour la connexion à une base de données Microsoft SQL Server (version 7.0 ou ultérieure) et d'exécuter des commandes. Les classes ADO.NET Data Provider sont les suivantes :
  • 119.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 119 Nous allons détailler leur utilisation dans la suite de ce chapitre. 2. Accès direct aux données Pour obtenir simplement des informations avec accès simples, on doit suivre ces étapes: • Créer les objets Connection, Command et DataReader, • Utiliser le DataReader pour récupérer l’information de la base de données, et l'afficher dans un contrôle, • Fermer la connexion, • Envoyer la page à l'utilisateur. À ce stade, les informations que l’utilisateur voit et l'information dans la base de données n'ont plus aucun lien, et tous les objets ADO.NET ont été détruits. Pour ajouter ou mettre à jour l'information on suit ces étapes: • Créer les objets connection et command, • Exécuter la commande (avec l’instruction SQL appropriée). 1. Créer une Connexion Avant de récupérer ou mettre à jour les données, il faut établir une connexion à la source de données. En général, le nombre de connexions est limité (licence ou charge du serveur). Il faut donc garder une connexion ouverte pour une durée aussi courte que possible, écrire le code dans un bloc try/catch et s’assurer de fermer la connexion. Pour créer un objet Connection, il faut spécifier une valeur pour sa propriété ConnectionString qui définit tous les détails pour trouver la source de données, se connecter et choisir une base de données initiale. Exemple: SqlConnection maConnection = new SqlConnection(); maConnection.ConnectionString = "Data Source=localhost;" + "Initial Catalog=Pubs;Integrated Security=SSPI"; Dans la ConnectionString : • Data source: indique le nom du serveur sur lequel la source de données se trouve. Si le serveur est sur le même ordinateur qui héberge le site ASP.NET, localhost est suffisant. • Initial catalog: nom de la base à accéder. "initial" signifie qu’on pourra la modifier par la suite en utilisant la méthode Connection.ChangeDatabase(). • Integrated security: indique que l’on se connecte à SQL Server en utilisant le compte utilisateur Windows qui exécute le code de page web, à condition de fournir une valeur de SSPI (Security Support Provider Interface). • Alternativement, on peut fournir un nom d'utilisateur et mot de passe définis dans la base de données pour l'authentification SQL Server.
  • 120.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 120 • ConnectionTimeout: durée d'attente, en secondes, avant de générer une erreur si on ne peut pas établir une connexion (défaut 15 sec; 0: pas de limite) 2. Comment stocker la Connection String? Généralement, tout le code de l’application utilise la même chaîne de connexion pour utiliser la BD. On peut donc stocker une chaîne de connexion dans une variable membre de classe ou, mieux, un fichier de configuration. On peut aussi créer un objet de connexion et fournir la chaîne de connexion en une seule étape en utilisant un constructeur dédié : SqlConnection maConnection = new SqlConnection(connectionString); // maConnection.ConnectionString is now set to connectionString. 3. Se Connecter Ouvrir la connexion se fait à l’aide de l’instruction maConnection.Open(); L’instruction maConnection.Close(); Ferme la connexion. Une autre approche est possible qui utilise using: 4. La Commande Select Pour récupérer les données il faut : • Une instruction SQL qui sélectionne l’information souhaitée, • Un objet Command qui éxécute l’instruction SQL , • Un objet DataReader ou DataSet pour accéder aux enregistrements.
  • 121.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 121 Exemple: SqlCommand maCommand = maConnection.CreateCommand(); maCommand.CommandText = "SELECT CustomerID, CompanyName from Customers"; Ou avec un constructeur : SqlCommand thisCommand = new SqlCommand("SELECT CustomerID, CompanyName from Customers", thisConnection); Exemple de sélection
  • 122.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 122 Exemple de mise à jour 5. Utiliser un DataSet Un dataset permet l’accès déconnecté à une BD. Dans ce cas, on se connecte pour charger le DataSet et on se déconnecte aussitôt. Les raisons pour l’utilisation d’un dataset sont nombreuses : • Faire quelque chose qui consomme beaucoup de temps avec les données, • Utiliser la liaison de données ASP.NET pour remplir un contrôle Web (une grille) avec les données. Dans ce cas l’approche par DataSet est plus simple, • Pour naviguer dans les 2 sens dans les données (DataReader va uniquement vers l’avant), • L’utilisation du DataSet, permet de stocker plusieurs tables et de définir des relations entre elles, • Pour enregistrer les données dans un fichier pour une utilisation ultérieure puisqu’un DataSet peut être sauvegardé au format XML dans un fichier ordinaire. Les applications ADO.NET utilisent le DataSet pour stocker des données, mais pas pour faire des mises à jour. Pour faire des update, il est préférable d’utiliser des commandes directes. Pour extraire des enregistrements et les placer dans un DataSet, il faut utiliser un DataAdapter. Chaque DataAdapter peut contenir quatre commandes: SelectCommand, InsertCommand, UpdateCommand et DeleteCommand. Cela permet d'utiliser un seul Objet DataAdapter pour des tâches multiples.
  • 123.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 123 Exemple avec un DataSet 6. Utiliser des Relations L’exemple suivant illustre l’utilisation des relations dans ADO.NET
  • 124.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 124 7. Commandes paramétrées Pour éviter les injections SQL est pouvoir utiliser des champs contenant des caractères spéciaux tels que les apostrophes, il faut utiliser des commandes paramétrées. Exemple : SqlCommand thisCommand = new SqlCommand("INSERT into Film (nom_realisateur, Titre ) values ( @param1 , @param2)", maConnection); SqlParameter param1 = new SqlParameter("@param1", SqlDbType.VarChar); SqlParameter param2 = new SqlParameter("@param2", SqlDbType.VarChar); param1.Value = TxtRealisateur.Text; param2.Value = txtTitreFilm.Text; thisCommand.Parameters.Add(param1); thisCommand.Parameters.Add(param2); thisCommand.ExecuteNonQuery(); 3. Introduction à Entity Framework L’intégration du code SQL dans le C# est délicat et long à déboguer. Avec Entity Framework Microsoft propose un mapping objet-relationnel avancé. Entity Framework est une technologie qui permet de créer une couche d'accès aux données (DAL pour Data Access Layer) liée à une base de données relationnelle. Il propose la création d'un schéma conceptuel composé d'entités (en fait des classes) qui permettent la manipulation d'une source de données, sans écrire une seule ligne. Entity Framework assure l'indépendance du schéma conceptuel (entités ou objets) du schéma logique de la base de données - les tables. Pratique : 1. Créez une BD Contacts et une table Contact selon le schéma suivant :
  • 125.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 125 2. Créez un projet console GestionDesContacts 3. Faites un clic droit sur le projet  Ajouter  Nouvel Élément  Modèle de donnée ADO.NET entité. Nommez le nouvel objet Contact.edmx. Puis cliquez sur Ajouter. Choisir Générer à partir de la BD. Dans l’écran suivant choisir la chaîne de connexion qui correspond à votre base de donnée (ici Contacts.dbo) puis cliquez sur Suivant. 4. Incluez les tables qui vous intéressent puis cliquez sur Terminer.
  • 126.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 126 Vous devriez obtenir ceci dans votre application : Si vous affichez les classes de votre projet (en cliquant sur Class View), vous devriez voir apparaître 2 nouvelles classes qui ont été créées à partir de la BD : 5. Désormais pour manipuler la BD on passera par ces classes, et donc plus besoin de rédiger le code nécessaire pour ouvrir la connexion, créer les commandes et les exécuter. Entity Framework se charge de tout.
  • 127.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 127 6. Exemple : Voilà le code pour ajouter un contact et l’insérer à la BD. Ce code utilise les 2 classes ContactEntities et Contact pour réaliser ces opérations :
  • 128.
    Le langage C#Collège Maisonneuve Fayçal Abouzaid Page 128 Références Beaucoup d’exemples sont adaptés de : Sam A. Abolrous, Learn C#, Wordware Publishing, Inc., 2008 Autres références utilisées: Christian Nagel, Jay Glynn, Morgan Skinner, Professional C# 5.0 and .NET 4.5.1, Wiley Publishing, 2014 John Sharp, Microsoft Visual C# 2010 étape par étape, Microsoft Press, Dunod, 2010. Christain Nagel & al, Professional C#4 and .NET4, Wiley Publishing, 2010. Serge Tahé , APPRENTISSAGE DU LANGAGE C# 2008 et du Framework .NET 3.5 - ISTIA - Université d'Angers, Mai 2008. Microsoft : http://msdn.microsoft.com/fr-ca/vcsharp/aa336706