Introduction au
Introduction au
langage C#
langage C#
Qu
Qu
’
’
est
est
-
-
ce que C#
ce que C#
?
?
C# est un langage de programmation orienté objet et à base de composants, simple et moderne, qui ressemble à C++ et à Java.
C# est présenté comme le langage de base de la stratégie .NET de Microsoft.
Il est inclus dans l’environnement de développement intégré Visual Studio .NET de même que Visual Basic .NET, Visual C++.Net , Visual J# et JScript.
Tous ces langages permettent l’accès à l'ensemble des composants de l'architecture .NET, dont le moteur
d’exécution appelé le CLR (Common Language
C# & le Framework .Net
C# & le Framework .Net
C# est le langage principal de .NET Framework et son utilisation comporte les avantages suivants:
les types de données de C# correspondent exactement au CLR (Common Language Runtime) sans couche intermédiaire et C# peut présenter ainsi un petit avantage de performance;
dans la documentation Microsoft, beaucoup d'exemples sont donnés en C# uniquement ;
C# a une syntaxe plus stricte et plus sûre, et exclut l’utilisation de typage implicite ;
C# a des fonctions de documentation de type XML intégrées dans le langage ;
C# a une syntaxe plus familière pour les programmeurs C, C++, Java et Perl.
L
L
’
’
environnement
environnement
Visual
Visual
Studio
Studio
.Net
.Net
Visual Studio .Net est un environnement
de développement riche en outils
contenant toutes les fonctionnalités
nécessaires à la création de projets C#,
VB.Net, C++.Net, J#, JScript.
Premi
Premi
è
è
re application C#
re application C#
using System;namespace TextHello {
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1 {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
public static void Main(string[] args) {
Console.WriteLine("Hello world"); }
} }
L
L
’
’
explorateur de solutions
explorateur de solutions
L’explorateur de
solution est une
fenêtre qui montre les
fichiers qui
composent la solution
sous forme d’une
Fichiers de la solution
Fichiers de la solution
TextHello.sln
C’est le fichier le plus haut de la solution. Il y en a un par application.
Tout fichier de solution contient un ou plusieurs fichiers de projet.
Dans le système de fichiers, tout fichier de solution porte l’extension .sln.
Dans l’explorateur de solutions, il apparaît avec un nom plus facile à lire, comme « Solution ‘TextHello’ » dans ce projet.
Fichiers de la solution(2)
Fichiers de la solution(2)
TextHello.csproj
C’est un fichier de projet C#.
Tout fichier de projet contient un ou plusieurs fichiers source.
Les fichiers source d’un même projet doivent être rédigés dans le même langage de programmation. Ce type de fichier s’affiche dans l’explorateur de
solutions uniquement à l’aide du nom du projet, mais est stocké dans le système de fichiers avec
Fichiers de la solution(3)
Fichiers de la solution(3)
Classe1.cs
C’est un fichier source C#, dans lequel vous
allez rédiger votre code.
Il contient un peu de code généré
automatiquement par Visual Studio.Net et
qu’on va examiner sous peu.
Fichiers de la solution(4)
Fichiers de la solution(4)
AssemblyInfo.cs
C’est un autre fichier source C#.
Ce fichier permet d’ajouter des attributs à
votre programme, comme le nom de l’auteur,
la date de rédaction du programme, etc.
Il existe d’autres attributs plus avancés
permettant d’agir sur la façon dont s’exécute
le programme.
Fichiers de la solution(5)
Fichiers de la solution(5)
App.ico
C’est l’icône associé à l’application.
Toutes les applications Windows possédant
une interface utilisateur disposent d’une icône
affichée sous forme réduite dans la barre des
tâches lorsque l’application s’exécute.
Les espaces de noms
Les espaces de noms
Une ressource dans le code source a la possibilité d’être déclarée et définie à l’intérieur d’un espace de noms.
Si une ressource n’est déclarée dans aucun espace de noms elle fait partie d’un espace de noms global et
anonyme.
using Toto1;
using Toto1.Toto2;
using System;
namespace Toto1
{ // ici les ressources de l'espace de noms Toto1
namespace Toto2
{ // ici les ressources de l'espace de noms Toto1.Toto2
}
Cr
Cr
é
é
ation d
ation d
’
’
une documentation
une documentation
à
à
l
l
’
’
aide XML et de commentaires
aide XML et de commentaires
Dans Visual C#, il est possible de créer la
documentation pour le code en incluant des
balises XML. dans les champs de commentaires
directement avant le bloc de code auquel elles
se réfèrent
Exemple :
/// <summary>
/// The main entry point for the application.
Cr
Cr
é
é
ation d
ation d
’
’
une documentation
une documentation
à
à
l
l
’
’
aide XML et de commentaires
aide XML et de commentaires
Voici quelques exemples de balises :
<summary> description</summary> : utilisée pour décrire un type ou un membre d'un type.
<remarks>description</remarks> : ajout des informations complémentaires à une description de type.
<para>contenu</para> : est à utiliser à l'intérieur d'une autre balise, telle que <summary>, <remarks> ou <returns>, et vous permet de structurer le texte.
Se référer à msdn pour une liste complète des balises XML pour les commentaires: http://msdn2.microsoft.com/fr-fr/library/5ast78ax(VS.80).aspx
Cr
Cr
é
é
ation d
ation d
’
’
une documentation
une documentation
à
à
l
l
’
’
aide XML et de commentaires
aide XML et de commentaires
Une fois le code
documenté, il est possible de générer des pages
Web de commentaires à partir de Visual studio comme suit:
Il suffit d’aller dans le
menu Outils et de cliquer sur Générer les pages Web de commentaires.
La m
La m
é
é
thode Main() (1/2)
thode Main() (1/2)
Chaque assemblage exécutable a au moins une méthode statique Main() dans une de ses classes. Cette méthode représente le point d’entrée du
programme, c’est-à-dire que le thread principal créé
automatiquement lorsque le processus se lance va commencer par exécuter le code de cette méthode.
Il peut y avoir éventuellement plusieurs méthodes Main() (chacune dans une classe différente) par programme. Le cas échéant, il faut préciser au compilateur quelle
méthode Main() constitue le point d’entrée du programme.
La m
La m
é
é
thode Main() (2/2)
thode Main() (2/2)
Le programme suivant ajoute les nombres passés en arguments en ligne de commande, et affiche le résultat. S’il n’y a pas d’argument, le programme le signale :
using System;
class Prog {
static void Main(string[] args) { if (args.Length == 0)
Console.WriteLine("Entrez des nombres à ajouter.");
else { long result = 0;
foreach( string s in args ) result += Int64.Parse(s);
// la méthode Parse Convertit une chaîne de caractère // en un entier 64-bit signé équivalent.
Les commentaires
Les commentaires
Il existe trois façons de commenter du texte dans un fichier source C# :
Le texte placé entre les balises /* suivie de */ est commenté. Ces balises peuvent éventuellement se trouver sur deux lignes différentes.
Si une ligne contient la balise // alors le texte de cette ligne qui suit cette balise est commenté.
Si une ligne contient la balise /// alors le texte de cette ligne qui suit cette balise est commenté. De plus ce texte fera partie de la documentation automatique.
Types de donn
Types de donn
é
é
es C# pr
es C# pr
é
é
d
d
é
é
finis
finis
(1/2)
(1/2)
Il existe 6 catégories de types prédéfinis
C#:
Référence:
object,
object
string
string
Signé:
sbyte
sbyte
, short,
, short,
int
int
, long
, long
Non signé:
byte,
byte,
ushort
ushort
,
,
uint
uint
,
,
ulong
ulong
Caractère :
char
char
Point flottant :
float, double, decimal
float, double, decimal
Types de donn
Types de donn
é
é
es C# pr
es C# pr
é
é
d
d
é
é
finis
finis
(2/2)
(2/2)
Les types prédéfinis sont des alias des
types CTS définis dans le framework .Net.
Exemple:
Le type
int est un alias de
int
System.Int32
System.Int32
Int32 est une structure qui appartient à
l’espace de nom System
Types entiers:
-32768 à 32767 16-bit signed integer
System.Int16 short
0 à
18446744073709551615 64-bit unsigned integer
System.UInt64 ulong
0 à 4294967295 32-bit unsigned integer
System.UInt32 uint
0 à 65535 16-bit unsigned integer
System.UInt16 ushort
0 à 255 8-bit unsigned integer
System.Byte byte
( -263 à 263 – 1 ) 64-bit signed integer
System.Int64 long
-2147483648 à 2147483647 32-bit signed integer
System.Int32 int
-128 à 127 8-bit signed integer
System.SByte sbyte Rang de Valeurs Description CTS Type Name
N’importe quel caractère Unicode (16 bit) 2 _ System.Char char Approximativement ±1.0 x 10-28 à ±7.9 x 1028 12 OUI System.Decimal decimal Approximativement ±5.0 x 10-324 à ±1.7 x 10308 8 OUI System.Double double Approximativement ±1.5 x 10-45 à ±3.4 x 1038 4 OUI System.Single float 0 à 18446744073709551615 8 Non System.Uint64 ulong 0 à 4294967295 4 Non System.UInt32 uint 0 à 65535 2 Non System.Uint16 ushort 0 à 255 1 Non System.Byte byte -9223372036854775808 à 9223372036854775807 8 OUI System.Int64 long -2147483648 à 2147483647 4 OUI System.Int32 int -32768 à 32767 2 OUI System.Int16 short -128 à 127 1 OUI System.Sbyte sbyte Valeurs Possibles Octets Occupés Signé? .Net Framework (System) type C# Type Types de données:
\x Un caractère unicode spécifié par son code
hexadécimal. Exemple: \xc8
\u Un caractère unicode spécifié par son numéro.
Exemple: \u200
\v Tabulation verticale (Vertical Tab)
\t Tabulation horizontale (Horizontal Tab)
\r Retour chariot (Carriage Return)
\n Nouvelle ligne (New Line)
\b Retour arrière (Backspace)
\\ \ \" " \' ' Séquence d’Échappement Caractère Caractères d'échappement
Variables & Types de Donn
Variables & Types de Donn
é
é
es
es
Déclaration de Variables :
Étape 1 : Déterminer le Type de données à utiliser. Étape 2 : Créer le nom de la Variable.
Étape 3 : Terminer par un point-virgule. Exemple : int compteur; double taux;
Initialisation de Variables :
Étape 1 : Utiliser l’opérateur de l’affectation. Étape 2 : Détermine la valeur à assigner. Étape 3 : Terminer par un point-virgule.
Cha
Cha
î
î
nes de caract
nes de caract
è
è
res
res
Une chaîne de caractères peut être déclarée et
initialisée de plusieurs façons:
string s = "Hello World";
Résultat : Hello World
string s = "\"Hello\""; Résultat : "Hello" string s = "Hello\nWorld"; Résultat : Hello World string s = @”C:\Test\SubDirectory”;
Constantes
Constantes
Les constantes en C# se déclare avec le
mot clé const
Exemple :
const
int
MAX_EMPLOYES =
3000
;
const
string
SQL_CONNECTION_STRING =
“
database=Northwind;user_id =moi; password
Les conversions entre nombres et
Les conversions entre nombres et
cha
cha
î
î
nes de caract
nes de caract
è
è
res
res
nombre -> chaîne : "" + nombre chaine -> int : int.Parse(chaine) ou Int32.Parse(chaine) chaîne -> long : long.Parse(chaine) ou Int64.Parse(chaine) chaîne -> double : double.Parse(chaîne) ou Double.Parse(chaîne) chaîne -> float : float.Parse(chaîne) ou Float.Parse(chaîne)
Erreurs de conversions
Erreurs de conversions
La conversion d'une chaîne vers un
nombre peut échouer si la chaîne ne
représente pas un nombre valide. Il y a
alors génération d'une erreur fatale.
Erreurs de conversions
Erreurs de conversions
Cette erreur peut être gérée par la clause
try/catch suivante :
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
instruction suivante;
Si la fonction ne génère pas d'exception, on
passe alors à instruction suivante, sinon on
passe dans le corps de la clause catch puis à
Exemple
Exemple
// espaces de noms importés
using System;
// la classe de test
public class conv1{
public static void Main(){
string S;
const int i=10;
const long l=100000; const float f=45.78F; double d=-14.98; // nombre --> chaîne S=""+i; affiche(S); S=""+l; affiche(S); S=""+f; affiche(S); S=""+d; affiche(S);
//boolean --> chaîne
const bool b=false; S=""+b; affiche(S); // chaîne --> int int i1; i1=int.Parse("10"); affiche(""+i1); try{ i1=int.Parse("10.67"); affiche(""+i1);
} catch (Exception e){
affiche("Erreur "+e.Message); // chaîne --> long long l1; l1=long.Parse("100"); affiche(""+l1); try{ l1=long.Parse("10.675"); affiche(""+l1);
} catch (Exception e){
affiche("Erreur "+e.Message); }
// chaîne --> double double d1; d1=double.Parse("100,87"); affiche(""+d1); try{ d1=double.Parse("abcd"); affiche(""+d1);
} catch (Exception e){
affiche("Erreur "+e.Message); } // chaîne --> float float f1; f1=float.Parse("100,87"); affiche(""+f1); try{ d1=float.Parse("abcd"); affiche(""+f1);
} catch (Exception e){
affiche("Erreur "+e.Message); }
}// fin main
public static void affiche(String S){ Console.
WriteLine("S="+S); }
Ex
Ex
é
é
cution de l
cution de l
’
’
exemple
exemple
Les résultats obtenus sont les suivants :
S=10 S=100000 S=45,78 S=-14,98 S=False S=10
S=Erreur The input string was not in a correct format. S=100
S=Erreur The input string was not in a correct format. S=100,87
S=Erreur The input string was not in a correct format. S=100,87
S=Erreur The input string was not in a correct format.
On remarquera que les nombres réels sous forme de chaîne de
caractères doivent utiliser la virgule et non le point décimal. Ainsi on écrira double d1=10.7; mais double d2=int.Parse("10,7");
Il est possible, dans une expression, de changer
momentanément le codage d'une valeur.
On appelle cela changer le type d'une donnée
ou en anglais type casting.
La syntaxe du changement du type d'une valeur
dans une expression est la suivante:
(
type
) valeur
La valeur prend alors le type indiqué. Cela
entraîne un changement de codage de la valeur.
Les changements de type
Exemple:
int i, j;
float isurj;
isurj= (float)i/j; // priorité de () sur /
Ici il est nécessaire de changer le type de i ou j en réel sinon la division donnera le quotient entier et non réel.
i est une valeur codée de façon exacte sur 2 octets
(float) i est la même valeur codée de façon approchée
en réel sur 4 octets
Il y a donc transcodage de la valeur de i. Ce
transcodage n'a lieu que le temps d'un calcul, la variable
i conservant toujours son type int.
Les changements de type
Les tableaux de donn
Les tableaux de donn
é
é
es
es
Un tableau C# est un objet permettant de rassembler sous un même identificateur des données de même type.
Sa déclaration est la suivante :
Type[] Tableau=new Type[n]
n est le nombre de données que peut contenir le tableau.
La syntaxe Tableau[i] désigne la donnée n°i où i
appartient à l'intervalle [0,n-1].
Toute référence à la donnée Tableau[i] où i n'appartient pas à l'intervalle [0,n-1] provoquera une exception.
Un tableau peut être initialisé en même temps que déclaré : int[] entiers=new int[] {0,10,20,30};
Les tableaux de donn
Les tableaux de donn
é
é
es
es
Les tableaux ont une propriété Length qui est le nombre d'éléments du tableau.
Un tableau à deux dimensions pourra être déclaré comme suit : Type[,] Tableau=new Type[n,m];
où n est le nombre de lignes, m le nombre de colonnes. La syntaxe Tableau[i,j] désigne l'élément j de la ligne i de Tableau.
Le tableau à deux dimensions peut lui aussi être initialisé en même temps qu'il est déclaré :
Les tableaux de donn
Les tableaux de donn
é
é
es
es
Le nombre d'éléments dans chacune des dimensions peut être obtenue par la méthode GetLenth(i) où i=0 représente la dimension correspondant au 1er indice, i=1 la dimension correspondant au 2ième indice, … Un tableau de tableaux est déclaré comme suit :
Type
[][] Tableau=new
Type[n
][];
La déclaration ci-dessus crée un tableau de n lignes.
Chaque élément Tableau[i] est une référence de tableau à une dimension.
Ces tableaux ne sont pas créés lors de la déclaration ci-dessus.
Exemple 1
Exemple 1
// un tableau de tableaux
string[][] noms=new string[3][]; for (int i=0;i<noms.Length;i++){
noms[i]=new string[i+1]; } //for
// initialisation
for (int i=0;i<noms.Length;i++){ for(int j=0;j<noms[i].Length;j++){
noms[i][j]="nom"+i+j; }//for j
}//for i
• Ici noms[i] est un tableau de i+1 éléments.
•Comme noms[i] est un
tableau, noms[i].Length est son nombre d'éléments.
Exemple 2 (1/4)
Exemple 2 (1/4)
using System;
// classe de test
public class test {
public static void Main(){
// un tableau à 1 dimension initialisé
int[] entiers=new int[] {0,10,20,30};
for (int i=0;i<entiers.Length;i++){
Console.WriteLine("entiers["+i+"]="+entiers[i]);
}//for
Exemple 2 (2/4)
Exemple 2 (2/4)
// un tableau à 2 dimensions initialisé
double[,] reels=new double[,] { {0.5, 1.7}, {8.4, -6}};
for (int i=0;i<reels.GetLength(0);i++){
for (int j=0;j<reels.GetLength(1);j++){
Console. WriteLine("reels["+i+","+j+"]="+reels[i,j]);
}//for j
Exemple 2 (3/4)
Exemple 2 (3/4)
// un tableau de tableaux
string[][] noms=new string[3][]; for (int i=0;i<noms.Length;i++){ noms[i]=new string[i+1];
}//for
// initialisation
for (int i=0;i<noms.Length;i++){ for(int j=0;j<noms[i].Length;j++){
noms[i][j]="nom"+i+j; }//for j
Exemple 2 (4/4)
Exemple 2 (4/4)
// affichage
for (int i=0;i<noms.Length;i++){ for(int j=0;j<noms[i].Length;j++){ Console.Out.WriteLine("noms["+i+"]["+j+"]="+noms[i][j]); }//for j }//for i }//Main }//class
Ex
Ex
é
é
cution de l
cution de l
’
’
exemple
exemple
entiers[0]=0 entiers[1]=10 entiers[2]=20 entiers[3]=30 reels[0,0]=0.5 reels[0,1]=1.7 reels[1,0]=8.4 reels[1,1]=-6 noms[0][0]=nom00 noms[1][0]=nom10 noms[1][1]=nom11 noms[2][0]=nom20 noms[2][1]=nom21
Les op
Les op
é
é
rateurs
rateurs
Opérateur d’affectation:
Forme générale : V1=V2=....=Vn=expression
Expression arithmétique
Les opérateurs des expressions arithmétiques sont les suivants :
+ addition - soustraction
* multiplication
/ division : le résultat est le quotient exact si l'un au moins
des opérandes est réel. Si les deux opérandes sont entiers le résultat est le quotient entier. Ainsi 5/2 -> 2 et 5.0/2 ->2.5. % division : le résultat est le reste quelque soit la nature des opérandes, le quotient étant lui entier. C'est donc l'opération
Exemple
Exemple
class Binary {
public static void Main() { int x, y, result; float floatResult; x = 7;y = 5; result = x+y; Console.WriteLine("x+y: {0}", result); result = x-y; Console.WriteLine("x-y: {0}", result); result = x*y; result = x/y Console.WriteLine("x/y: {0}", result); floatResult = (float)x/(float)y; Console.WriteLine("x/y: {0}", floatResult); result = x%y; Console.WriteLine("x%y: {0}", result); result += x; Console.WriteLine("result+=x: {0}", result); } }
Ex
Ex
é
é
cution de l
cution de l
’
’
exemple
exemple
x+y: 12
x-y: 2
x*y: 35
x/y: 1
x/y: 1.4
x%y: 2
result+=x: 9
Les op
Les op
é
é
rateurs
rateurs
Il existe diverses fonctions mathématiques. En voici quelques-unes :
double Sqrt(double x) racine carrée double Cos(double x) Cosinus
double Sin(double x) Sinus
double Tan(double x) Tangente
double Pow(double x,double y) x à la puissance y (x>0) double Exp(double x) Exponentielle
double Log(double x) Logarithme népérien double Abs(double x) valeur absolue
Les op
Les op
é
é
rateurs
rateurs
Toutes ces fonctions sont définies dans
une classe C# appelée Math.
Lorsqu'on les utilise, il faut les préfixer
avec le nom de la classe où elles sont
définies.
Ainsi on écrira :
double x, y=4;
x=Math.Sqrt(y);
Les op
Les op
é
é
rateurs
rateurs
Priorités dans l'évaluation des expressions
arithmétiques :
La priorité des opérateurs lors de l'évaluation
d'une expression arithmétique est la suivante
(du plus prioritaire au moins prioritaire) :
[
fonctions
], [
( )
],[
*
,
/
,
%
], [
+
,
-
]
Remarque :
Les opérateurs d'un même bloc [ ] ont même priorité.
Opérateurs relationnels:
<, <=, ==, !=, >, >= Priorités:
1. >, >=, <, <=
2. ==, !=
Le résultat d'une expression relationnelle est le booléen false si expression fausse true sinon. Exemple :
boolean fin;
int x; fin=x>4;
Les op
Les op
Les op
é
é
rateurs
rateurs
Comparaison de deux caractères:
Il es possible de comparer deux caractères
avec les opérateurs relationnels.
Ce sont alors leurs codes ASCII, qui sont des
nombres, qui sont alors comparés.
On rappelle que selon l'ordre ASCII on a les
relations suivantes :
espace < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. <'z'
Comparaison de deux chaînes de caractères:
Elles sont comparées caractère par caractère.
La première inégalité rencontrée entre deux caractères induit une inégalité de même sens sur les chaînes.
Cette dernière inégalité permet de dire que "Chat" < "Chien".
Les op
Les op
é
é
rateurs
rateurs
'a'
'h'
'C'
"chat"
'i'
<
'h'
=
'C'
=
"chien"
Exemple :
comparaison des
chaînes chat et
chien
Opérateurs booléens:
NOT ( ! ) AND ( && ) OR ( || )Exemple:
bool fin; int x; fin= x>2 && x<4;Les opérateurs relationnels ont priorité sur les
opérateurs && et ||.
Les op
Les op
Les op
é
é
rateurs
rateurs
Opérateurs de traitement de bits: Soient i et j deux entiers.
i<<n décale i de n bits sur la gauche. Les bits entrants sont des zéros.
i>>n décale i de n bits sur la droite. Si i est un entier signé (signed char, int, long) le bit de signe est préservé.
i & j fait le ET logique de i et j bit à bit. i | j fait le OU logique de i et j bit à bit. ~i complémente i à 1
Les op
Les op
é
é
rateurs
rateurs
Combinaison d'opérateurs:
a=a+b peut s'écrire a+=b
a=a-b peut s'écrire a-=b
Opérateurs d'incrémentation et de
décrémentation:
La notation variable++ signifie
variable=variable+1 ou encore variable+=1
La notation variable-- signifie
Les op
Les op
é
é
rateurs
rateurs
L'opérateur ternaire « ? »
L'expression
expr_cond ? expr1:expr2
est
évaluée de la façon suivante :
1. l'expression expr_cond est évaluée. C'est une expression conditionnelle à valeur vrai ou faux
2. Si elle est vraie, la valeur de l'expression est celle de expr1. expr2 n'est pas évaluée.
3. Si elle est fausse, c'est l'inverse qui se produit : la valeur de l'expression est celle de expr2. expr1 n'est pas évaluée.
Les op
Les op
é
é
rateurs
rateurs
Exemple:
L'opération
i=(j>4 ? j+1:j-1);
affectera à la
variable i : j+1 si j>4, j-1 sinon.
C'est la même chose que d'écrire if(j>4) i=j+1;
Structures de contrôle
Structures de contrôle
Une structure de contrôle est un élément
du programme qui change le
comportement par défaut de l’unité
d’exécution (du thread).
Rappelons que ce comportement par
défaut est d’exécuter les instructions les
unes à la suite des autres.
Structures de contrôle
Structures de contrôle
Les conditions:
Il existe trois types de conditions:
if/else
switch
if( b == true ) // si b vaut true alors...
if( i >= 4 && i<= 6) // si i dans l'intervalle fermé [4,6] alors...
if( i < 4 || i > 6) // si i hors de l'intervalle fermé [4,6] alors...
...
// s="bonjour" si i strictement inférieur à j, sinon s="hello"
string s = i<j ? "bonjour" : "hello"; ...
switch(i) {
case 1: Console.WriteLine("i vaut 1");
break;
case 6: Console.WriteLine("i vaut 6");
break;
default:Console.WriteLine("i ne vaut ni 1 ni 6");
break;
Exemples
Structures de contrôle
Structures de contrôle
Les boucles
Il existe quatres types de boucles:
while
do/while
for
int i=0;int j=8;
while( i < 6 && j > 9 ) {
i++;j--; }
int i=0;int j=8;
do
{
i++;j--; }
while( i < 6 && j > 9)
for(int i = 1; i<=6 ; i++) ...
int i = 3;int j=5;
for(; i<7 && j>1 ;i++ , j--)...
for( int i =6 ; i<9 ; ) { ... i++;}
int[] tab = {1,3,4,8,2};
// Calcul de la somme des éléments du tableau.
int Somme = 0;
foreach(int i in tab ) Somme += i;
// Somme vaut : 1+3+4+8+2 = 18
Exemples
Les
Les
é
é
num
num
é
é
rations
rations
Une énumération est un type de données dont le domaine de valeurs est un ensemble de constantes entières.
Considérons un programme qui a à gérer des mentions à un examen.
Il y en aurait cinq : Passable, AssezBien, Bien, TrèsBien,Excellent.
On pourrait alors définir une énumération pour ces cinq constantes :
Les
Les
é
é
num
num
é
é
rations
rations
De façon interne, ces cinq constantes sont
codées par des entiers consécutifs
commençant par 0 pour la première constante,
1 pour la suivante, etc...
Une variable peut être déclarée comme
prenant ces valeurs dans l'énumération :
Exemples :
1. mention maMention=mention.Passable;
2. if(maMention==mention.Passable) {
La gestion des exceptions
La gestion des exceptions
De nombreuses fonctions C# sont susceptibles
de générer des exceptions, c'est à dire des
erreurs.
Lorsqu'une fonction est susceptible de générer
une exception, le programmeur devrait la gérer
dans le but d'obtenir des programmes plus
résistants aux erreurs.
Il faut toujours éviter le "plantage" sauvage
d'une application.
La gestion des exceptions
La gestion des exceptions
La gestion d'une exception se fait selon le
schéma suivant :
try
{
appel de la fonction susceptible de générer
l'exception
}
catch (Exception e)
{
traiter l'exception e
}
La gestion des exceptions
La gestion des exceptions
Si la fonction ne génère pas d'exception, on
passe alors à instruction suivante, sinon on
passe dans le corps de la clause catch puis à
instruction suivante.
Notons les points suivants :
e est un objet dérivé du type Exception.
On peut être plus précis en utilisant des types tels que IOException, SystemException, etc… : il existe plusieurs types d'exceptions.
En écrivant catch (Exception e), on indique qu'on veut gérer toutes les types d'exceptions.
La gestion des exceptions
La gestion des exceptions
Si le code de la clause try est susceptible de générer plusieurs types d'exceptions, on peut vouloir être plus
précis en gérant l'exception avec plusieurs clauses catch :
try {
appel de la fonction susceptible de générer l'exception
} catch (IOException e){ traiter l'exception e }
} catch (SystemException e){ traiter l'exception e }
La gestion des exceptions
La gestion des exceptions
Dans la clause catch, on peut ne pas vouloir utiliser l'objet Exception disponible. Au lieu d'écrire catch (Exception e){..}, on écrit alors
catch (Exception){...} ou catch {...}.
On peut ajouter aux clauses try/catch, une clause finally :
try{
appel de la fonction susceptible de générer l'exception } catch (Exception e){
traiter l'exception e }
finally{
code exécuté après try ou catch }
instruction suivante
Qu'il y ait exception ou pas, le code de la clause finally sera toujours exécuté.
La gestion des exceptions
La gestion des exceptions
La classe Exception a une propriété Message qui est un message détaillant l'erreur qui s'est produite. Ainsi si on veut afficher celui-ci, on écrira :
catch (Exception ex){
Console.Error.WriteLine("L'erreur suivante s'est produite : "+ex.Message);
...
}//catch
La classe Exception a une méthode ToString qui rend une chaîne de caractères indiquant le type de l'exception ainsi que la valeur de la propriété Message. On pourra ainsi écrire :
catch (Exception ex){
Console.Error.WriteLine("L'erreur suivante s'est produite : "+ex.ToString());
Exemple
Exemple
using System;
public class Prog {
public static void Main() { try { int i = 1; int j = 0; int k = i/j; } catch(System.DivideByZeroException) {
Console.WriteLine("Une division entière par zéro a eu lieu!"); }
} }
Exemple 2
Exemple 2
L'exemple suivant montre une exception générée par l'utilisation d'un élément de tableau inexistant :
// tableaux // imports
using System;
public class tab1 {
public static void Main(String[] args){
// déclaration & initialisation d'un tableau int[] tab=new int[] {0,1,2,3};
int i;
// affichage tableau avec un for for (i=0; i<tab.Length; i++)
// affichage tableau avec un for each foreach (int élmt in tab)
Console.Out.WriteLine(élmt); // génération d'une exception
try{
tab[100]=6; }
catch (Exception e){
Console.Error.WriteLine("L'erreur suivante s'est produite : " + e.Messge); }//try-catch finally{ String attente=Console.ReadLine(); } }//Main }//classe
R
R
é
é
sultat de l
sultat de l
’
’
exemple
exemple
tab[0]=0 tab[1]=1 tab[2]=2 tab[3]=3 0 1 2 3
L'erreur suivante s'est produite : System.IndexOutOfRangeException: Exception of type System.IndexOutOfRangeException was thrown. at tab1.Main(String[] args)
Exemple 3
Exemple 3
Voici un autre exemple où on gère l'exception provoquée par l'affectation d'une chaîne de caractères à un nombre lorsque la chaîne ne représente pas un nombre :
// imports
using System;
public class console1{
public static void Main(String[] args){ // On demande le nom System.Console.Write("Nom : "); // lecture réponse String nom=System.Console.ReadLine(); // on demande l'âge int age=0;
Boolean ageOK=false; while ( ! ageOK){ // question Console.Out.Write("âge : "); // lecture-vérification réponse try{ age=int.Parse(System.Console.ReadLine()); ageOK=true; } catch {
Console.Error.WriteLine("Age incorrect, recommencez..."); }//try-catch
}//while
// affichage final
Console.Out.WriteLine("Vous vous appelez " + nom + " et vous avez " + age + " ans");
Console.ReadLine(); }//Main
R
R
é
é
sultat de l
sultat de l
’
’
exemple
exemple
Nom : dupont
âge : xx
Age incorrect, recommencez...
âge : 12
Vous vous appelez dupont et vous avez 12
ans
Passage de param
Passage de param
è
è
tres
tres
à
à
une
une
fonction
fonction
Les paramètres déclarés dans la signature
d’une fonction sont appelés paramètres
formels.
Lorsqu’on appelle une fonction, on lui
passe des variables qui vont être recopiés
dans les paramètres formels pour
effectuer le calcul. Cela sont appelés
paramètres effectifs.
Exemple
Exemple
private static void changeInt(int a){ a=30;
Console.Out.WriteLine("Paramètre formel a="+a); }
public static void Main(){ int age=20;
changeInt(age);
Console.Out.WriteLine("Paramètre effectif age="+age); }
Ici a est un paramètre formel Ici age est un paramètre effectif
Passage par valeur
Passage par valeur
La valeur du paramètre effectif est
recopiée dans le paramètre formel
correspondant.
On a deux entités distinctes.
Si la fonction modifie le paramètre formel,
le paramètre effectif n'est lui en rien
Exemple
Exemple
// passage de paramètres par valeur à une fonction
using System;
public class param2{
public static void Main(){ int age=20;
changeInt(age);
Console.Out.WriteLine("Paramètre effectif age="+age); }
private static void changeInt(int a){ a=30;
Console.Out.WriteLine("Paramètre formel a="+a); }
R
R
é
é
sultat
sultat
Paramètre formel a=30
Paramètre effectif age=20
La valeur 20 du paramètre effectif a été recopiée
dans le paramètre formel a. Celui-ci a été
ensuite modifié.
Le paramètre effectif est lui resté inchangé.
Ce mode de passage convient aux paramètres
d'entrée d'une fonction.
Passage par r
Passage par r
é
é
f
f
é
é
rence
rence
Dans un passage par référence, le
paramètre effectif et le paramètre formel
sont une seule et même entité.
Si la fonction modifie le paramètre formel,
le paramètre effectif est lui aussi modifié.
En C#, ils doivent être tous deux précédés
du mot clé ref.
Exemple
Exemple
// passage de paramètres par valeur à une fonction
using System;
public class param2{
public static void Main(){ int age=20;
changeInt(ref age);
Console.Out.WriteLine("Paramètre effectif age="+age); }
private static void changeInt(ref int a){ a=30;
Console.Out.WriteLine("Paramètre formel a="+a); }
R
R
é
é
sultat
sultat
Le résultat de l’exécution de l’exemple
précédent est le suivant :
Paramètre formel a=30 Paramètre effectif age=30
Le paramètre effectif a suivi la modification du
paramètre formel.
Ce mode de passage convient aux paramètres
de sortie d'une fonction.
Passage par r
Passage par r
é
é
f
f
é
é
rence avec le mot
rence avec le mot
cl
cl
é
é
out
out
Considérons l'exemple précédent dans lequel la variable age ne serait pas initialisée avant l'appel à la fonction changeInt :
// passage de paramètres par valeur à une fonction
using System;
public class param2{
public static void Main(){ int age;
changeInt(ref age);
Console.Out.WriteLine("Paramètre effectif age="+age); }
private static void changeInt(ref int a){ a=30;
Console.Out.WriteLine("Paramètre formel a="+a); }
Lorsqu'on compile ce programme, on a une
erreur :
Use of unassigned local variable 'age‘
On peut contourner l'obstacle en affectant une
valeur initiale à age.
On peut aussi remplacer le mot clé ref par le
mot clé out.
On exprime alors que la paramètre est
uniquement un paramètre de sortie et on'a donc
pas besoin de valeur initiale.
Passage par r
Passage par r
é
é
f
f
é
é
rence avec le mot
rence avec le mot
cl
Exemple
Exemple
// passage de paramètres par valeur à une fonction
using System;
public class param2{
public static void Main(){ int age=20;
changeInt(out age);
Console.Out.WriteLine("Paramètre effectif age="+age); }
private static void changeInt(out int a){ a=30;
Console.Out.WriteLine("Paramètre formel a="+a); }
Remarque
Remarque
Passage d'un objet à une fonction:
Quand un objet est passé comme paramètre
à une fonction il est passé par référence et ne
pas par valeur.
Ceci provient du fait que les objets sont de
type référence. Il n’y a donc pas recopie du
paramètre effectif objet dans le paramètre
formel objet.
Les classes
Les classes
Une classe est une combinaison de code
(méthodes) et de données (attributs)
C’est une sorte de « moule » à partir
duquel on crée des objets (instances).
Les classes : exemple
Les classes : exemple
public class personne { // attributs
private string prenom; private string nom; private int age;
// méthode d’initialisation : constructeur public personne(string P, string N, int age){
prenom=P; nom=N;
this.age=age; }
// méthode
public void identifie(){
Console.Out.WriteLine(prenom+","+nom+","+age); }
Les classes
Les classes
Les membres ou champs d'une classe peuvent être des données (attributs), des méthodes (fonctions), des
propriétés.
Ces champs peuvent être accompagnés de l'un des trois mots clés suivants :
privé (private) n'est accessible que par les seules méthodes internes de la classe
public (public) est accessible par toute fonction définie ou non au sein de la classe
protégé (protected) n'est accessible que par les seules méthodes internes de la classe ou d'un objet dérivé (voir ultérieurement le concept d'héritage).
En général, les données d'une classe sont déclarées privées alors que ses méthodes et propriétés sont
Les classes
Les classes
Une classe est instancié par le biais de
l’opérateur
new
.
Exemple:
Personne p=
new
Personne("Ali","Taha",30);
Le mot clef
this
fait référence à l’objet en
cours.
Constructeur d
Constructeur d
’
’
une classe
une classe
Un constructeur est une méthode spéciale
qui sert à initialiser un objet lors de sa
création.
Il porte toujours le nom de la classe pour
laquelle il est définie.
Il est public et n’as pas de type de retour
Une classe peut avoir un ou plusieurs
constructeurs.
Constructeur d
Constructeur d
’
’
une classe
une classe
Il existe trois types de constructeurs :
Par défaut : pour la création puis l’initialisation d’un
objet dans le cas ou le programmeur omet de donner des valeurs.
Paramétré: pour la création puis l’initialisation d’un
objet avec des valeurs données par le programmeur .
Par recopie: pour la création puis l’initialisation d’un
Exemple
Exemple
using System;
public class personne{
// attributs
private string prenom; private string nom; private int age;
// constructeur par défaut
public personne() { this.prenom= ""; this.nom=""; this.age=0; }
Exemple
Exemple
// constructeur paramétré
public personne(String P, String N, int age){ this.prenom=P;
this.nom=N; this.age=age; }
// constructeur par recopie
public personne(personne P){ prenom=P.prenom; nom=P.nom; this.age=P.age } // méthode
public void identifie(){
Console.Out.WriteLine(prenom+","+nom+","+age); }
Voici un court programme de test :
using System;
public class test1{
public static void Main(){
personne p1=new personne("Ali","Taha",30); Console.Out.Write("p1=");
p1.identifie();
personne p2=new personne(p1); Console.Out.Write("p2=");
p2.identifie(); }
}
et les résultats obtenus :
p1=Ali,Taha,30 p2=Ali,Taha,30
Les propri
Les propri
é
é
t
t
é
é
s
s
L’expérience de la programmation nous as enseigné que pour
chaque attribut privé d’une classe il faut prévoir deux méthodes pour la lecture et pour la modification de cet attribut.
On appelle ces méthodes des accesseurs/modifieurs ou getter/setter methods.
Ainsi pour l’attribut prenom de la classe personne par exemple il faut prévoir les méthodes:
public String getPrenom() {
return prenom; }
public void setPrenom(String P)
{
Les propri
Les propri
é
é
t
t
é
é
s
s
Les propriétés permettent d’éviter la lourdeur de
ces méthodes accesseurs/modifieurs.
Elles permettent de manipuler des attributs
privés comme s'ils étaient publics.
Leurs forme est comme suit:
public type propriété{ get {...}
set {...} }
Les propri
Les propri
é
é
t
t
é
é
s
s
Ainsi pour l’attribut « prenom » de l’exemple on
les déclarre comme suit:
public string Prenom{
get { return prenom; } set { prenom = value; } }
Ainsi Prenom="ali" est équivalent à l’appel de la
méthode setPrenom("ali") par exemple.
Il faut cependant remarquer que
Exemple
Exemple
using System;
public class personne{
// attributs
private String _prenom; private String _nom; private int _age;
// constructeurs
public personne(String P, String N, int age){ this._prenom=P; this._nom=N; this._age=age; } public personne(personne P){ this._prenom=P._prenom; this._nom=P._nom; this._age=P._age;
// identifie
public void identifie(){
Console.Out.WriteLine(_prenom+","+_nom+","+_age); }
// propriétés
public string prenom{
get { return _prenom; } set { _prenom=value; } }//prenom
public string nom{
get { return _nom; } set { _nom=value; } }//nom
public int age{
get { return _age; } set {
// age valide ?
if(value>=0){ _age=value; } else
throw new Exception("âge ("+value+") invalide"); }//if
Exemple d
Exemple d
’
’
appel
appel
using System; public class test1{
public static void Main(){
personne P=new personne("Ali","Omar",34);
Console.Out.WriteLine("P=("+P.prenom+","+P.nom+","+P.age+")"); P.age=56;
Console.Out.WriteLine("P=("+P.prenom+","+P.nom+","+P.age+")"); try{
P.age=-4;
} catch (Exception ex){
Console.Error.WriteLine(ex.Message); }//try-catch }//Main }//classe Résultat : P=(Ali, Omar,34) P=(Ali, Omar,56)
Les m
Les m
é
é
thodes et attributs de
thodes et attributs de
classe
classe
On appelle méthodes ou attributs de classe un
attribut ou une méthode qui ne dépendent pas
d’un objet particulier.
On les appelle méthodes ou attributs statiques:
c-à-d qu’on précède leur déclaration avec le mot
clé static.
Exemple :
private static long _nbPersonnes; // nombre d’objets personnes créées
Exercice
Exercice
Ajouter un attribut de classe
_nbPersonnes qui compte le nombre
d’objets personnes créées et une propriété
nbPersonnes pour l’exemple précédent et
donner un exemple d’utilisation.
Solution
Solution
using System;
public class personne{
// attributs de classe
private static long _nbPersonnes=0;
// attributs d'instance
private String _prenom; private String _nom; private int _age;
// constructeurs
public personne(String P, String N, int age){
// une personne de plus
_nbPersonnes++; this._prenom=P; this._nom=N; this._age=age;
public personne(personne P) {
// une personne de plus
_nbPersonnes++; this._prenom=P._prenom; this._nom=P._nom; this._age=P._age; } // identifie
public void identifie() {
Console.Out.WriteLine(_prenom+","+_nom+","+_age); }
// propriété de classe
public static long nbPersonnes { get{ return _nbPersonnes;} }//nbPersonnes
// propriétés d'instance
public string prenom{
get { return _prenom; } set { _prenom=value; } }//prenom
public string nom{
get { return _nom; } set { _nom=value; } }//nom
public int age{
get { return _age; } set {
// age valide ? if(value>=0){ _age=value; } else
throw new Exception("âge ("+value+") invalide"); }//if
Utilisation
Utilisation
using System; public class test1{
public static void Main(){
personne p1=new personne("Jean","Dupont",30); personne p2=new personne(p1);
new personne(p1);
Console.Out.WriteLine("Nombre de personnes créées : "+personne.nbPersonnes);
}// main
}//test1
Résultat :
L
L
’
’
h
h
é
é
ritage
ritage
Le but de l'héritage est de "personnaliser" une classe existante pour qu'elle satisfasse à nos besoins.
Supposons qu'on veuille créer une classe enseignant : un enseignant est une personne particulière.
Il a des attributs qu'une autre personne n'aura pas : la matière qu'il enseigne par exemple. Mais il a aussi les attributs de toute
personne : prénom, nom et âge.
Un enseignant fait donc pleinement partie de la classe personne mais a des attributs supplémentaires.
Plutôt que d'écrire une classe enseignant à partir de rien, on
préfèrerait reprendre l'acquis de la classe personne qu'on adapterait au caractère particulier des enseignants.
Exemple
Exemple
using System;
public class enseignant : personne {
// attributs
private int _section;
// constructeur
public enseignant(string P, string N, int age,int section) : base(P,N,age) { this._section=section;
// suivi
Console.Out.WriteLine("Construction enseignant(string,string,int,int)");
}//constructeur
// propriété section
public int section{ get { return _section; } set { _section=value; }
}// section
La classe enseignant rajoute aux méthodes et
attributs de la classe personne :
un attribut section qui est le n°de section auquel
appartient l'enseignant dans le corps des enseignants (une section par discipline en gros)
un nouveau constructeur permettant d'initialiser tous les attributs d'un enseignant
La déclaration :
public class enseignant : personne {