Cours C# pour BTS SIO : Introduction et Programmation
Cours C# pour BTS SIO : Introduction et Programmation
Démarrage en C#
COURS C#
Date Révision
Août 2018 Création (v95)
Décembre 2020 Modification pour adaptation SLAM2 (v.102)
1 Généralités.............................................................................................................................5
1.1 Introduction.....................................................................................................................5
1.2 Prérequis.........................................................................................................................5
1.3 Objectifs..........................................................................................................................5
2 Programmation C#.................................................................................................................6
2.1 Environnement de développement.................................................................................6
2.2 Structure d'un programme C#........................................................................................6
2.2.1 Commentaires /* et */..............................................................................................7
2.2.2 Blocs { et }................................................................................................................7
2.2.3 Bibliothèques (using)...............................................................................................7
2.3 En résumé.......................................................................................................................8
2.4 Syntaxe d’écriture...........................................................................................................8
2.5 Les instructions...............................................................................................................9
2.6 Auto-évaluation chapitre 1............................................................................................10
3 Types de données................................................................................................................11
3.1 Les types primitifs.........................................................................................................11
3.1.1 Déclaration d'une variable primitive......................................................................12
3.1.2 affectation d'une variable primitive........................................................................12
3.2 Les constantes..............................................................................................................12
3.3 Déclaration d’une variable sans type : var....................................................................12
3.4 Les classes conteneurs................................................................................................13
3.4.1 Déclaration.............................................................................................................13
3.4.2 affectation..............................................................................................................13
3.4.3 Utilisation des classes conteneurs........................................................................13
3.5 Les conversions............................................................................................................14
3.5.1 Conversions implicites...........................................................................................14
3.5.2 Conversions explicites...........................................................................................14
3.5.3 Conversions de chaîne vers nombre.....................................................................14
3.5.3.1 La méthode ‘Convert.’.......................................................................................................14
3.5.4 Conversions de nombre vers chaîne.....................................................................15
3.5.4.1 La méthode ‘toString’.........................................................................................................15
4 Les opérations......................................................................................................................16
4.1 Les opérations arithmétiques........................................................................................16
4.1.1 Opérations simples................................................................................................16
4.1.2 Opérations complexes...........................................................................................16
4.1.3 Opérations particulières.........................................................................................16
4.2 Les opérations binaires.................................................................................................16
4.3 Les opérations de chaînes............................................................................................17
4.3.1 Formatage des affichages.....................................................................................17
5 Les tableaux.........................................................................................................................19
5.1.1 déclaration.............................................................................................................19
5.1.2 affectation..............................................................................................................19
7 Exercice................................................................................................................................26
7.1 Enregistrer un fichier contenant une fiche contact.......................................................26
7.2 Source fichier................................................................................................................26
8 Boucles et conditions...........................................................................................................27
8.1 Boucles.........................................................................................................................27
8.1.1 Boucle for ou Foreach...........................................................................................27
8.1.2 Boucle while...........................................................................................................27
8.1.3 Boucle Do… while.................................................................................................28
8.2 Conditions.....................................................................................................................28
8.2.1 Conditions IF - ELSE.............................................................................................28
8.2.2 Conditions SWITCH - CASE.................................................................................29
8.2.3 Portée de variables................................................................................................29
9 Les fonctions........................................................................................................................31
9.1 Création d’une fonction.................................................................................................32
9.2 Appel d’une fonction......................................................................................................32
9.3 Entraînez-vous : fonction SaisirNombre(int min, int max)............................................33
10 Les exceptions...................................................................................................................34
10.1 Arborescence des exceptions.....................................................................................34
10.1.1 Exemple de code avec erreur.............................................................................34
10.2 Gestion des exceptions rencontrées..........................................................................35
10.2.1 Exemple de code avec gestion d’erreur..............................................................35
12 Les objets...........................................................................................................................42
12.1 Vocabulaire.................................................................................................................42
12.2 Représentation............................................................................................................42
12.2.1 instanciation.........................................................................................................43
12.2.2 Accesseurs et mutateurs.....................................................................................44
12.2.3 Portées et modificateurs......................................................................................44
12.2.3.1 pour les classes...............................................................................................................44
12.2.3.2 Pour les méthodes...........................................................................................................44
12.2.3.3 Pour les attributs..............................................................................................................45
12.2.4 Analyse d’un programme.....................................................................................45
12.3 Résumé.......................................................................................................................46
12.4 Héritage......................................................................................................................47
12.4.1 Exemple...............................................................................................................47
12.4.2 Déclaration...........................................................................................................47
12.4.3 Utilisation.............................................................................................................48
12.4.4 Exemple de codage (TD à reproduire)................................................................48
12.4.5 Exercice...............................................................................................................50
14 Annexes..............................................................................................................................54
1 GÉNÉRALITÉS
1.1 INTRODUCTION
Vous avez déjà des notions de programmation, dans un autre langage. Ce support s'appuie sur
votre compréhension des boucles, des conditions et des fonctions.
Chaque langage utilise sa propre syntaxe et ses propres mots clés, mais les principes fondamentaux
restent les mêmes : C# est un langage créé par Microsoft, pour séduire les programmateurs C tout
en apportant la rigueur de gestion et la virtualisation de Java.
Ainsi, on retrouve ces deux langages dans le fonctionnement de C#.
1.2 PRÉREQUIS
Ce support de cours s'adresse aux étudiants ayant déjà suivi le cours SI4 et ayant acquis les notions
suivantes :
• Les variables et les constantes
• Les tableaux (à une ou plusieurs dimensions)
• Les boucles (répétitions de type 'for', 'do while' et 'while')
• Les conditions (tests utilisant 'if … elseif… else')
• les fonctions (déclarations, passage de paramètres, valeurs de retour, appels)
1.3 OBJECTIFS
C# est un langage qui entre dans la famille des machines virtuelles. À ce titre, il n'est n'y vraiment
compilé (le compilateur ne renvoie pas un exécutable binaire), ni interprété… cependant, son
fonctionnement le rapproche des langages compilés et son environnement de travail aussi.
Vous saurez donc :
• rédiger un programme
• appeler des bibliothèques
• compiler un programme
• utiliser l'environnement de travail pour déboguer
2 PROGRAMMATION C#
La première chose à faire est d'installer un environnement de développement (aussi appelé IDE
pour integrated development environment).
namespace HelloWorld
{
class Program
{
static void Main(string[] args) {
Console.WriteLine("Hello World");
Console.ReadKey();
}
}
}
2.2.1 COMMENTAIRES /* ET */
Pour C#, les lignes comprises entre /* et */ ne sont pas lues : cela permet au programmeur de
placer des commentaires avant un code complexe, ou bien décrire rapidement ce que fait
l’application.
Il est important de comprendre qu’il faut une convention d’écriture commune à tous les
programmeurs. On utilise donc des balises ouvrantes et fermantes, un peu comme en français, les
symboles ‟ et ” indique que le texte contenu entre les deux symboles et dit à haute voix par
exemple.
Sur une ligne seulement (ou bien après une instruction) C# accepte le double symbole //.
2.2.2 BLOCS { ET }
L’utilisation de blocs, permet à l’interpréteur C# de comprendre que l’ensemble des instructions
comprises entre { et } vont ensemble et constituent un bloc non-sécable.
Ici, namespace est une sorte de classeur qui contient tout le programme. Si le programme est
constitué de plusieurs fichiers, ils doivent avoir le même namespace. Ici, le programme n’est
constitué que d’une seule classe ‘Program’ qui elle-même ne contient qu’une méthode ‘Main’.
Cette structure permet de découper un programme en section logique (on regroupe ensemble, les classes et fonctions
qui agissent de manière similaire ou qui ont un lien commun sur les données ou les interfaces). Si vous ne comprenez
pas cette phrase, c’est tout à fait normal lorsque l’on commence à programmer avec un langage comme celui-ci…
2.3 EN RÉSUMÉ
Le schéma ci-après donne un exemple d’analogie possibles
• Les fonctions (appelées aussi méthodes) et variables ne commencent pas par une majuscule.
Considérez qu’une fonction est un regroupement d’instructions qui seront exécutées lignes
après lignes, jusqu’à la fin du bloc fonction.
• C# utilise la notation "camel" à l’exception des règles sur la première lettre. Ainsi, une méthode
(fonction) pour colorier un rectangle s’écrira "colorierRectangle". Seules les classes s’écrivent
avec la première lettre en majuscule
• Les variables peuvent utiliser tous les caractères alphabétiques (accentués compris) mais ne
peuvent commencer par un chiffre, ou porter le nom d’un mot-clé de C#
• Les conditions seront encadrées par des parenthèses ().
• Les blocs d’instructions seront encadrés par des crochets {}
• Un commentaire d’une ligne commencera par deux ‘slash’ //
• Un bloc de commentaires (plusieurs lignes) s’écrit entre /* et */
• Un bloc de commentaires pour C#doc s’écrit entre /** et */
• Les crochets carrés sont utilisés pour les tableaux [ ]
• Le point ( . ) est généralement utilisé pour lier les méthodes (fonctions) aux variables (objets),
c’est le lien entre le sujet et le verbe (moi.Écrire(quelquechose) ou document.Imprimer(), etc.)
En cliquant sur ► Démarrer, une console doit s’ouvrir et afficher notre message.
Voici quelques questions pour valider votre compréhension et approfondir vos connaissances…
Réponses :
Faux c’est point-virgule ; Faux c’est regroupé dans un bloc ; Vrai ; Faux car contient un symbole (‘) ; Faux using
intègre les bibliothèques ; Vrai.
3 TYPES DE DONNÉES
Dans les langages de programmation typés, c’est le programmeur qui choisit l’espace de valeurs
pour les variables. En Python ou PHP (qui ne sont pas typés), l’interpréteur suppose le type
automatiquement. En C#, C++, Java et de nombreux autres langages, le programmeur peut
optimiser son code (pour le rendre plus performant en vitesse et occupation mémoire) en
choisissant lui-même le type de ses variables.
En Java, le type non-signé n'existent pas. Pour obtenir une valeur de type signé en utilisant un type
non-signé, il suffit d'appliquer un masque booléen de la taille du type de variable.
valeur = valeur & 0xFF…
unEntier = 25;
uneLettre = 'c';
3.4.1 DÉCLARATION
Int32 unEntier;
String unMot;
Boolean monDrapeau;
3.4.2 AFFECTATION
unEntier = 25;
unMot = "Bonjour le monde";
monDrapeau = true; // ne peut prendre que true ou false
En effet, certaines méthodes ne permettent que l’utilisation d’objet (comme les méthodes de la classe ArrayList). Il était
nécessaire d’encapsuler les types primitifs dans un objet. Par exemple :
int myInt = 5 ;
list.add(new Int32(myInt)) ; // ce mécanisme de boxing est relativement lourd. Les classes conteneurs facilitent tout.
Pour synthétiser, un byte est inclus dans un short qui est inclus dans un int qui est inclus dans un long qui est inclus
dans un float qui est inclus dans un double. Un char sera inclus uniquement à partir d’un int, car il n’a pas de bit de
signe.
On peut convertir
En entier En entier non-signé En décimal Autre
ToInt16 ToUint16 ToDecimal (128 bits) ToBoolean
ToInt32 ToUint32 ToDouble (64 bits) ToDateTime
ToInt64 ToUint64
4 LES OPÉRATIONS
Les priorités sont respectées (multiplication et division passent avant l’addition et la soustraction)
Attention à ne pas confondre opérations binaires et comparateurs (&&, ||, !=, ==, ≥=, <=... )
Voir https://msdn.microsoft.com/en-us/library/system.string(v=vs.110).aspx
5 LES TABLEAUX
Un tableau est un ensemble de variables de même type dans une quantité définie.
Chaque case du tableau est numérotée, en partant de 0 : un tableau contenant 10 valeurs aura les
numéros de cases de 0 à 9 (on parle de l’indice de cellule).
5.1.1 DÉCLARATION
0 1 2 3 4 5
1995 1996 1997 1998 2000 2001
Une autre déclaration (pour un tableau de chaîne vide par exemple) est la suivante :
String[] monTableau = new String[9];
String[] autreTableau = new String[9];
Ces deux tableaux contiendront donc 10 chaînes de caractères (l’index commence à 0 !).
int tailleTableau = autreTableau.length;
Enfin, il est possible d’utiliser des tableaux à plusieurs dimensions (comme pour la bataille navale) :
byte[,] monTableau = new byte[5,4];
int[,] autreTableau2D = {{1,2,3},{4,5,6},{7,8,9}};
Le premier tableau est une grille de 10x10 éléments tandis que le deuxième tableau contient 3x3
éléments. Il faut donc voir les tableaux à dimensions multiples comme des tableaux de tableau.
5.1.2 AFFECTATION
AutreTableau2D[0,1] = 666;
Console.writeLine("la case coordonnées 0,1 a pour valeur "+autreTableau[0,1]);
En C#, les entrées et sorties concernent autant le mode console, que les fichiers et connexions.
Seule la gestion des interfaces graphiques est différente (utilise les notions d’événements). Les
notions utiles sont :
• Stream : un flux qui ne s’arrête pas, comme une émission en direct à la télévision
• Buffer : une zone mémoire pour ne pas perdre d’information (notamment si le flux n’est pas lu
suffisamment souvent).
6.1.1 AFFICHAGE
Voici comment comprendre le code d’affichage suivant :
Console.writeLine("Bonjour !");
• System est la classe utilisée pour l’affichage sur une console. Il n’est pas nécessaire de la
déclarer si "using System" est placé en entête du programme.
• Console est l’objet dans cette classe, qui gère les sorties : ici, l’objet console est l’écran
principal de la console. Il existe un objet error qui permet de noter les erreurs. L’objet in est
utilisé pour récupérer les flux du clavier.
• WriteLine() est la méthode qui s’applique sur l’objet out : cette méthode envoie à cet objet les
données comprises entre ses parenthèses. .
Exemple :
Console.writeLine("Coco !"); // affichera 'Bonjour Coco !' sur la même ligne
Console.Error.WriteLine("Un problème"); // affichera 'Un problème'
6.1.2 SAISIE
La console est ouverte par défaut, ainsi que le flux en provenance du clavier (plus pratique qu’en
Java).
String reponse = Console.ReadLine(); // attend [Entrée] et stocke les données
ConsoleKeyInfo car = Console.ReadKey(); // attend l'appui d'une touche
Le type pour récupérer le résultat de ReadKey() est un type objet. Nous verrons cela plus tard.
Il n’existe pas de lecture de clavier caractère par caractère qui ne serait pas bloquant.
6.1.3 DEBUG
Il existe une classe en C# qui permet d’afficher des informations dans la console du débogueur.
Pour cela, il faut activer la bibliothèque correspondante :
using System.Diagnostics ;
Enfin, pour visualiser la console dans Visual Studio, utilisez la séquence de touches CTRL+Alt+O
D’autres options sont disponibles pour une meilleure mise en forme, comme :
Debug.Indent() ;
Debug.Unindent() ;
L’intérêt de cette solution, est de ne pas polluer la console du programme principale, ou bien d’être
utilisable dans les programmes de type WinForm.
6.2 FICHIERS
L’astuce ci-dessus nous amène à nous intéresser à la lecture et l’écriture de fichier.
Comme évoqué précédemment, pour C#, la plupart des périphériques sont considérés comme des
flux entrants et sortants. Cela signifie que si le flux n’est pas mémorisé, les données transmises sont
perdues (un peu comme une chaîne en direct : si vous êtes absent de l’écran, les informations sont
perdues).
Comme la plupart des périphériques acceptent les entrées et les sorties, cela multiplie par deux les
flux et buffets à déclarer.
Attention, la lecture d’un flux vide entraîne la génération d’une exception qui bloque l’exécution du programme.
Ainsi, la plupart du temps (et c’est aussi vrai en Java), il faudra ouvrir le flux et ouvrir un buffet :
1. Ouvrir le flux du fichier
2. Ouvrir le buffet du flux du fichier
3. Lire/Écrire dans le buffet
4. Fermer le buffet
5. Fermer le flux
Voici donc un exemple de code pour lire un fichier texte, à copier tel quel pour le moment :
using System;
using System.IO;
using System.Text;
namespace FileReadExample
{
class Program
{
static void Main(string[] args) {
FileStream monFlux = null; // Créer un objet flux (en direct)
StreamReader reader = null; // Créer un objet lecteur de flux (bufferise)
String fileContent = "";
try {
// Ouverture
monFlux = File.OpenRead(@"e:\test.txt");
reader = new StreamReader(monFlux, Encoding.UTF8);
// Lecture
Console.WriteLine("Votre fichier contient : ");
fileContent = reader.ReadToEnd();
Console.WriteLine(fileContent);
}
catch (Exception ex) {
Console.WriteLine("Erreur de lecture !"+ex.Message);
}
finally {
// Fermeture
if (reader != null) {
reader.Dispose(); // Fermer le buffer (libère sa mémoire)
}
if (monFlux != null) {
monFlux.Dispose(); // Fermer le fichier (libère le canal)
}
Console.Write("** Appuyez sur une touche **");
Console.ReadKey();
}
}
}
}
namespace FileReadExample
{
class Program
{
static void Main(string[] args) {
FileStream monFlux = null; // Créer un objet flux (en direct)
StreamWriter writer = null; // Créer un objet de flux (bufferise)
try {
// Ouverture
monFlux = File.Open(@"e:\testwrite.txt", FileMode.Append);
writer = new StreamWriter(monFlux);
// Lecture
Console.WriteLine("Écriture réussi dans e:\\testwrite.txt ");
writer.WriteLine("Hello World pour les fichiers :");
}
catch {
Console.WriteLine("Erreur d'écriture !");
}
finally {
// Fermeture
if (writer != null) {
writer.Dispose(); // Fermer le buffer (libère sa mémoire)
}
if (monFlux != null) {
monFlux.Dispose(); // Fermer le fichier (libère le canal)
}
Console.Write("** Appuyez sur une touche **");
Console.ReadKey();
}
}
}
}
et le résultat :
7 EXERCICE
8 BOUCLES ET CONDITIONS
Comme dans d’autres langages, C# propose un ensemble d’instructions pour créer des boucles et
permettre des choix à l’aide de conditions.
8.1 BOUCLES
Il existe 3 boucles connues (répétition, test avant de commencer la boucle et test en fin de boucle).
On peut aussi créer une boucle infinie comme ceci (sortie possible avec une instruction ‘break’) :
for (;;) {
Console.writeLine("ne s'arrête jamais... ahahah !") ;
}
Enfin, lorsqu’on a un tableau ou une liste d’objet, on peut la parcourir automatiquement (foreach)
int[] maTable1 = { 3, 14, 1, 59, 2, 65 };
Console.WriteLine("Taille de la table = " + maTable1.Length);
foreach (int cpt in maTable1) {
Console.Write(":" + cpt + " "); //cpt prend les valeurs 3 puis 14 puis 1, 59...
}
Il est possible de sortir d’une boucle sans que la condition ne soit modifiée, par l’utilisation de l’instruction break !
int t=0;
while (t < 10) {
if (t = 5) {
break;
}
t++;
}
8.2 CONDITIONS
Il y a deux types de conditions :
• les IF, ELSE IF, ELSE
• les SWITCH, CASE
} else {
grade = 'F';
}
Console.writeLine("Grade = " + grade);
Il y a cependant un impératif : ajouter une instruction ‘break’ avant chaque nouveau bloc ‘case’,
sinon dès qu’une condition est réalisée, tous les blocs suivants sont exécutés.
Essayez le programme précédent en enlevant les mots-clés ‘break’. Le résultat est-il cohérent ?
D’autre part, en C#, la gestion des plages (intervalles) n’est pas intuitive ! Le code le plus proche est
le suivant :
switch (num) {
case 1: case 2: case 3: case 4: case 5:
Console.writeLine("testing case 1 to 5");
break;
case 6: case 7: case 8: case 9: case 10:
Console.writeLine("testing case 6 to 10");
break;
default:
//
}
Les utilisateurs de Pascal et Purebasic seront surpris du manque de souplesse mais PHP et C#
fonctionnent de la même manière que C#. Enfin, il n’y a pas de switch/case en Python.
int z = x*y;
}
Console.writeLine("Cette ligne entraine une erreur. Z = "+z);
}
9 LES FONCTIONS
Les fonctions simplifient et fiabilisent le codage. En effet, effectuer les mêmes actions plusieurs fois
à la suite peut se faire dans une boucle. Effectuer les mêmes actions à des moments différents
nécessite de pouvoir exécuter le même morceau de code à plusieurs endroits du programme.
Voici les deux possibilités :
Avoir plusieurs fois du code identique Appeler plusieurs fois un seul code
Il est évident que la deuxième solution est plus fiable, plus élégance et moins encombrante.
Une fonction est donc un bout de code, utilisable à plusieurs endroits.
Le travail que va faire la fonction Maximum est d’évaluer quel est le nombre le plus grand et de
renvoyer sa valeur.
Évidemment, il est possible de ne pas avoir de paramètre et/ou de ne pas renvoyer de valeur. Une
fonction qui imprime sur l’imprimante par défaut serait (cas fictif) :
public void Imprimer() {
SortirImprimanteVeille() ;
LancerImpressionSpooler() ;
}
Cette fonction – qui appelle deux fonctions – ne renvoie pas de valeur, d’où le mot-clé ‘void’ qui
signifie "vide". L’appel à une fonction sans valeur de retour se fait comme pour la fonction
SortirImprimanteVeille() ou LancerImpressionSpooler() ;
Aide N°1 :
Il faut utiliser une boucle, dont on ne sort que si le résultat est un nombre.
Aide N°2 :
La conversion d’une chaîne de caractère en entier utilise la fonction C# existante :
monNombre = Convert.ToInt16(maChaine)
Aide N°3 :
Il faudra utiliser les exceptions (try… catch) au moment de la conversion (voir chapitre suivant de ce
livre)
Réponse
using System;
namespace SaisirNombre
{
class Program
{
public static Int32 SaisirNombre(Int32 min, Int32 max) {
String maChaine = "";
Int32 nombre=0;
do {
Console.WriteLine("Saisissez un nombre entre "+min+" et "+max);
maChaine = Console.ReadLine();
if (maChaine != "") {
try {
nombre = Convert.ToInt32(maChaine);
}
catch {
maChaine = "";
}
}
} while ((maChaine == "") | (nombre > max) | (nombre < min));
return nombre;
}
10 LES EXCEPTIONS
C# fournit un moyen de contrôle des erreurs lors du déroulement des applications. Cette solution
se faisant au détriment de la performance et nécessitant du code supplémentaire, il est fréquent
que seules les parties sensibles du code soient protégées.
Voici les classes des objets liés aux erreurs fréquentes (par exemple, la lecture d’un index de
tableau au-delà de la taille maximale du tableau générera une exception
"ArrayIndexOutOfBounds").
int a=20;
int b=0;
Console.writeLine(a+" divisé par "+b+" égal "+a/b);
}
Ici, le programme ne traitera que cette erreur, mais il est possible de traiter chaque erreur (ou
exception) différemment : c’est l’ordre des catch {…} qui déterminera le premier traitement.
Il est également possible de récupérer le message d’erreur de l’exception, comme le montre le
code ci-dessous :
catch (Exception ex) {
Jusqu’à maintenant, nous avons programmé dans le mode console : il s’agit d’une interface
homme-machine austère mais facile à utiliser !
• L’ordinateur présente une information
• L’ordinateur attend une saisie… et ne fait rien d’autre
• Une fois la saisie effectuée, l’ordinateur continue le traitement
Cette programmation très séquentielle n’est pas celle utilisée sur les systèmes d’exploitation
graphiques.
11.1 FONCTIONNEMENT
Dans les OS modernes, c’est ce dernier qui gère tous les événements : le système "prête" des
ressources aux programmes. Une fenêtre, un champ de saisie, un bouton… ces éléments sont
dessinés et gérés par l’OS !
Dès lors, chaque clic, chaque action de l’utilisateur est enregistré par le système :
Lorsqu’il y a un événement qui concerne l’application, l’OS lui envoie le numéro de l’événement : le
programmeur décide s’il doit réagir à cet événement. L’avantage est qu’une application qui n’est
pas utilisée ne consommera pas de puissance à sa propre surveillance.
En C#, Visual Studio nous propose un éditeur graphique de fenêtre et masque une partie du
codage.
• La zone rouge contient la boite à outils : tous les éléments utilisables dans la fenêtre peuvent
être sélectionnés et placés sur celle-ci. Pour afficher la boite à outils : CTRL+Alt+X
Il faut comprendre la philosophie d’usage : et pour cela, parler légèrement du modèle MVC. Il s’agit d’un modèle qui
permet de simplifier le développement, en séparant la vue (les fenêtres, l’affichage), le contrôleur (les interactions de
l’utilisateur : clic, saisie au clavier, déplacement de souris…) et le modèle de stockage des données (une base, un fichier,
la mémoire…). MVC signifie Modèle – Vue – Contrôleur.
11.2.2.1 PROGRAM.CS
Il contient l’appel de la fenêtre graphique. Comme c’est une programmation événementielle, le
programme devient multi-tâche (il accepte notamment d’être géré par le système).
Visual Studio Sharp Develop
[STAThread] [STAThread]
static void Main() { private static void Main(string[] args) {
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1()); Application.Run(new MainForm());
} }
11.2.2.2 FORM.DESIGNER.CS
C’est le fichier qui contient la construction de la fenêtre. On y trouve notamment la fonction (on
dira "méthode") qui génère les composants de manière procédurale.
En effet, si vous devez créer 40 composants identiques (imaginez une application contenant un
champ par jour de la semaine), dessiner ces composants manuellement est fastidieux. La syntaxe
utilisée ici, permettra de générer dans une méthode conçue par le développeur, les composants
répétitifs.
private void InitializeComponent() {
this.textBox1 = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(32, 29);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(246, 20);
this.textBox1.TabIndex = 0;
//
// button1
//
this.button1.Location = new System.Drawing.Point(215, 70);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(62, 31);
this.button1.TabIndex = 1;
this.button1.Text = "Cliquez ici";
this.button1.UseVisualStyleBackColor = true;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(339, 131);
this.Controls.Add(this.button1);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
Notez que les attributs des composants sont suivis par les propriétés puis les valeurs :
this.button1.Text = "textBox1";
Cette ligne signifie que pour le composant button1, on place la valeur "Cliquez ici" dans la propriété
"Text".
11.2.2.3 FORM1.CS
C’est ce fichier qui contiendra les interactions entre l’utilisateur et l’interface du programme. Ainsi,
les lignes suivantes méritent d’être expliquées :
public Form1() {
InitializeComponent();
}
La méthode "Form1()" est publique, donc visible de partout. Elle ne contient qu’une ligne qui
appelle la construction de la fenêtre, dans le fichier Form1.Designer.cs.
La méthode "button1_Click()" correspond aux actions qui seront faites lorsque l’événement
correspondant est appelé. Ici, on affiche une simple boite d’alerte. Notez cependant, que cette
méthode reçoit deux paramètres : l’appelant (sender) et le type d’événement (e).
en effet, lors de l’initialisation des composants, on indique au système (dans le fichier
Form1.Designer.cs) que le programme surveillera les événements qui touchent à ce bouton :
this.button1.Click += new System.EventHandler(this.button1_Click);
Ces informations dépassent le niveau du module SI4 : il s’agit cependant d’une culture générale pour comprendre
comment fonctionne les applications dans les systèmes graphiques fenêtrés.
1 https://www.codeproject.com/Articles/1465/Beginning-C-Chapter-Using-Windows-Form-Controls
12 LES OBJETS
12.1 VOCABULAIRE
Le langage orienté objet propose un vocabulaire à connaître
impérativement. Ci-contre, la représentation symbolique d’une classe.
Une classe est constituée de membres :
• les attributs : ce sont les variables de la classe. Sauf s’ils sont publics,
les attributs ne sont pas visibles depuis une autre classe (étrangère).
• Les méthodes : ce sont les fonctions ou procédures de la classe. Elles
aussi peuvent être publiques ou privées.
Une classe n’est qu’un patron, un plan d’objet : il faut construire les objets à partir de ce plan, en
objet le terme utilisé : instancier.
Pour instancier une classe, on utilise une méthode de la classe particulière, qui porte le nom de la
classe, et qu’on appelle un constructeur.
12.2 REPRÉSENTATION
Voici un exemple graphique :
La
classe
Chat
contient les attributs privés couleurPelage, nom et age (un signe – les précède).
Elle contient les méthodes publiques (signe +) permettant de modifier ou lire les attributs : cela
signifie qu’il n’est possible de modifier ces attributs que par ces méthodes, ce qui est très
sécurisant.
12.2.1 INSTANCIATION
Pour créer le chat Félix, il suffit d’instancier la classe Chat et de stocker le résultat dans une
"variable" de type Chat (ce n’est pas un entier, une chaîne… c’est un chat).
La syntaxe d’instanciation est la suivante :
Chat felix = new Chat();
felix.changerNom("Felix");
felix.changerAge(5);
le mot-clé new indique à C# de construire un objet, mais comme pour une maison, l’objet est
initialement vide.
Notez qu’il n’est pas nécessaire de nommer l’objet avec le véritable nom du chat.
Chat chatRoumanet = new Chat() ;
chatRoumanet.changerNom("Pirouette") ;
…
A noter : si le constructeur de la classe n’est pas déclaré explicitement, C# va le créer automatiquement, avec tous les
attributs par défaut.
Astuce : il est possible d’avoir plusieurs constructeurs, à la condition que le nombre d’arguments
soit différents pour chaque constructeur et qu’il soit public (donc visible par tous).
Le mot-clé this permet de préciser à C# qu’il s’agit de l’attribut de l’objet en cours de création,
permettant de ne pas mélanger avec le nom de l’argument transmis :
public Chat() {}
12.3 RÉSUMÉ
Création d’une classe Déclaration d’un objet de la classe
(il
s’agit d’une réservation d’espace)
12.4 HÉRITAGE
L’intérêt majeur de la programmation objet est probablement l’héritage : cette notion permet
en effet de profiter des propriétés d’une classe existante et de pouvoir étendre ses capacités.
12.4.1 EXEMPLE
Une clinique vétérinaire qui doit enregistrer des chats et des chiens pourrait avoir deux
classes, comme dans l’image suivante :
12.4.2 DÉCLARATION
La déclaration d’un héritage de classe se fait par le symbole ' :' comme ci-dessous :
public class Chat : Animal {
public void griffer() {
Console.writeLine("Griffé !") ;
}
}
public class Chien : Animal {
public void mordre() {
Console.writeLine("Mordu !") ;
}
}
Contrairement au C++, En C# (et même en Java) une classe ne peut hériter que d’une seule classe.
12.4.3 UTILISATION
Une fois déclarée, la classe s’utilise normalement.
Chat monChat = new Chat();
Chien monChien = new Chien();
Animal maTortue = new Animal();
namespace Animal
{
public class Animal
{
protected String nom;
protected Int16 poids;
protected DateTime naissance;
Ici, naissance, nom et poids (ordre alphabétique) appartiennent bien à la classe Animal dans le
fichier Animal.cs.
La classe Chat étend la classe Animal en ajoutant le miaulement (méthode Miaule()) :
using System;
namespace Animal
{
class Chat : Animal
{
public Chat() {
this.nom = "Minou inconnu";
}
public String Miaule() {
return "Miaou";
}
}
}
namespace Animal
{
Le résultat sera :
12.4.5 EXERCICE
Finissez la classe Chat en ajoutant la méthode griffer(). Cette méthode contient un tirage au hasard
entre 0 et 0.999 et affichera
"le-nom-du-chat a essayé de vous griffer" si le tirage est supérieur à 0.8, sinon
"le-nom-du-chat vous aime bien et ne vous griffe pas".
Les classes sont des modèles pour créer des objets. Coder une classe ne permet pas de créer des
objets tant que l’on instancie pas la classe (xxx = new Class()) et que la classe ne contient pas de
constructeur.
Il est pourtant possible de créer des modèles de classe ou des modèles de méthodes. L’utilité est de
s’assurer que les utilisateurs de ces modèles proposeront bien des classes ayant des critères
communs, par exemple :
• Il existe plusieurs formes géométriques (en deux dimensions), pour chacune on veut obtenir la
surface et le périmètre. Les formules de calculs étant différentes, il faut fixer 2 méthodes Aire()
et Perimetre() que chaque codeur de forme devra utiliser
• Le remplissage d’une forme est commun à toutes les formes. Il n’est pas nécessaire que
chaque codeur ré-écrive une méthode de remplissage.
public Formes() {
couleurForme = 0;
aireForme = 0;
}
public void Remplissage(int color) {
this.couleurForme = color;
}
}
}
}
13.1.1 EXERCICE
Ajoutez une classe ‘Disque’ dont on calculera :
• le périmètre par la formule 2 * PI * valeurCalcul[0]
• l’aire par la formule PI * r²
Pour rappel, valeurCalcul est un tableau mais pour un disque, on n’utilise que le premier élément pour y placer le
rayon.
13.1.2 EXERCICE
Ajoutez une classe ‘Rectangle’ dont on calculera :
• le périmètre par la formule (valeurCalcul[0] + valeurCalcul[1])* 2 (P=(a+b)*2)
• l’aire par la formule valeurCalcul[0] * valeurCalcul[1] (A = a * b)
interface IAnimal {
string Name { get; }
void Move();
}
Ici, l’interface ‘Ianimal’ contient un atribut (public) ‘Name’ et une méthode (publique) Move().
Pour utiliser l’interface, il faut écrire le code suivant :
class Dog : IAnimal
{
private string m_name;
// On implémente la propriété Name accessible en lecture.
public string Name
{
get { return m_name; }
}
On crée notre propre attribut de stockage du nom en privé. Les utilisateurs de la classe ‘Dog’ ne
connaîtront jamais cet attribut et utiliseront ‘Name’ à la place : cela garantit le même usage par
tous !
Notez que la modification du nom du chien ne se fera qu’à l’instanciation de la classe : une fois nommé, le chien ne
changera plus de nom.
L’implémentation de la méthode Move() est similaire à une classe abstraite mais n’utilise pas
‘override’. L’oubli de cette implémentation donne lieu à un message clair du compilateur :
L’avantage principal est qu’une classe peut hériter de plusieurs interfaces (alors qu’une classe ne
peut hériter que d’une seule classe).
14 ANNEXES