1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
|
---
language: c#
contributors:
- ["Irfan Charania", "https://github.com/irfancharania"]
- ["Max Yankov", "https://github.com/golergka"]
- ["Melvyn Laïly", "http://x2a.yt"]
- ["Shaun McCarthy", "http://www.shaunmccarthy.com"]
translators:
- ["Olivier Hoarau", "https://github.com/Olwaro"]
filename: LearnCSharp-fr.cs
lang: fr-fr
---
C# est un langage de programmation orienté objet à typage fort qui permet aux développeurs de créer une grande variété d'applications fiables et robustes s'appuyant sur le framework .NET.
[Plus d'infos](http://msdn.microsoft.com/fr-fr/library/67ef8sbd.aspx)
```c#
// Les commentaires sur une seule ligne commencent par //
/*
Les
commentaires
multi-lignes
ressemblent
à
ceci
*/
/// <summary>
/// Ceci est un commentaire de documentation XML
/// </summary>
// Importez des namespaces avec l'instruction 'using'
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Threading.Tasks;
// Définit la portée du code pour une meilleure organisation
namespace Learning
{
// Chaque fichier .cs devrait au moins contenir une classe avec le même nom
// que celui du fichier. Ce n'est pas une obligation mais c'est mieux !
public class LearnCSharp
{
// LES BASES - si vous avez déjà de l'expérience en Java ou C++
// passez directement à la partie FONCTIONNALITÉS INTERÉSSANTES
public static void Syntax()
{
// Utilisez Console.WriteLine pour écrire sur la sortie
Console.WriteLine("Hello World");
Console.WriteLine(
"Entier: " + 10 +
" Double: " + 3.14 +
" Booleen: " + true);
// Pour omettre le retour à la ligne : Console.Write
Console.Write("Hello ");
Console.Write("World");
///////////////////////////////////////////////////
// Types et Variables
// Déclarez une variable avec la syntaxe <type> <nom>
///////////////////////////////////////////////////
// Sbyte - Entier signé sur 8 bits
// (-128 <= sbyte <= 127)
sbyte fooSbyte = 100;
// Byte - Entier non-signé sur 8 bits
// (0 <= byte <= 255)
byte fooByte = 100;
// Short - Entier sur 16 bits
// Signé - (-32,768 <= short <= 32,767)
// Non-signé - (0 <= ushort <= 65,535)
short fooShort = 10000;
ushort fooUshort = 10000;
// Int - Entier sur 32 bits
int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647)
uint fooUint = 1; // (0 <= uint <= 4,294,967,295)
// Long - Entier sur 64 bits
long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615)
// Par défaut le type d'un littéral entier est int ou uint
// on ajoute 'L' pour spécifier la création d'un long
// Double - Réel sur 64 bits en virgule flottante (norme IEEE 754)
double fooDouble = 123.4; // Precision : 15-16 chiffres
// Float - Réel sur 32 bits en virgule flottante (norme IEEE 754)
float fooFloat = 234.5f; // Precision : 7 chiffres
// Par défaut le type d'un littéral réel est double
// on ajoute 'f' pour spécifier la création d'un float
// Decimal - Type de donnée numérique sur 128 bits, fournit une plus
// grande précision et une plage de valeurs réduite.
// Approprié aux calculs financiers et monétaires
decimal fooDecimal = 150.3m;
// Booléen - vrai / faux
bool fooBoolean = true; // ou false
// Char - Un unique caractère Unicode sur 16 bits
char fooChar = 'A';
// String -- contrairement aux types précédents qui sont des types valeurs,
// string est un type référence. Il peut donc avoir la valeur null
string fooString = "\"échappement\" de guillemets et ajout de \n (nouvelle ligne) et de \t (tabulation)";
Console.WriteLine(fooString);
// Il est possible d'accéder à chaque caractère d'une chaîne de caractères via son index
char charFromString = fooString[1]; // 'é'
// une chaîne de caractères est immuable : impossible de faire fooString[1] = 'X';
// Comparaison de chaînes de caractères avec la culture courrante en ignorant la casse
string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase);
// Formatage
string fooFs = string.Format("Check Check, {0} {1}, {0} {1:0.0}", 1, 2);
// Dates et formatage
DateTime fooDate = DateTime.Now;
Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy"));
// Il est possible d'étaler une chaîne de caractères sur plusieurs lignes avec le symbole @.
// Pour échapper " utilisez ""
string bazString = @"Voici quelques trucs
sur une nouvelle ligne! ""Wow!"", quel style";
// Utilisez const ou read-only pour rendre une variable immuable.
// Les valeurs constantes sont calculées au moment de la compilation
const int HOURS_I_WORK_PER_WEEK = 9001;
///////////////////////////////////////////////////
// Structures de données
///////////////////////////////////////////////////
// Tableaux - indexé à partir de zéro
// La taille d'un tableau doit être décidée à la déclaration
// La syntaxe pour déclarer un tableau est la suivante :
// <type>[] <nom> = new <type>[<taille>]
int[] intArray = new int[10];
// Une autre méthode de déclaration et d'initialisation
int[] y = { 9000, 1000, 1337 };
// Indexer un tableau - Accéder à un élément
Console.WriteLine("intArray à 0: " + intArray[0]);
// Les tableaux sont muables.
intArray[1] = 1;
// Listes
// Elles sont plus souvent utilisées que les tableaux car plus souples
// La syntaxe pour déclarer une liste est la suivante :
// List<type> <nom> = new List<type>();
List<int> intList = new List<int>();
List<string> stringList = new List<string>();
List<int> z = new List<int> { 9000, 1000, 1337 }; // intialisation
// Les <> indiquent un type générique
// Pus d'info dans la partie FONCTIONNALITÉS INTERÉSSANTES
// Les éléments d'une liste ne sont pas null par défaut
// Il faut ajouter une valeur avant d'y accéder par index
intList.Add(1);
Console.WriteLine("intList à 0: " + intList[0]);
// Autres structures de données à étudier :
// Stack/Queue (Pile/File)
// Dictionary (une implémentation de hash map)
// HashSet (représente un ensemble)
// Collections en lecture seule
// Tuple (.Net 4+)
///////////////////////////////////////
// Opérateurs
///////////////////////////////////////
Console.WriteLine("\n->Opérateurs");
int i1 = 1, i2 = 2; // Raccourci pour des déclarations multiples
// Arithmétique classique
Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3
// Modulo
Console.WriteLine("11%3 = " + (11 % 3)); // => 2
// Opérateurs de comparaison
Console.WriteLine("3 == 2? " + (3 == 2)); // => False
Console.WriteLine("3 != 2? " + (3 != 2)); // => True
Console.WriteLine("3 > 2? " + (3 > 2)); // => True
Console.WriteLine("3 < 2? " + (3 < 2)); // => False
Console.WriteLine("2 <= 2? " + (2 <= 2)); // => True
Console.WriteLine("2 >= 2? " + (2 >= 2)); // => True
// Opérateurs bit à bit !
/*
~ Compément unaire
<< Décalage à gauche
>> Décalage à droite
& ET logique
^ OU exclusif
| OU inclusif
*/
// Incrémentations
int i = 0;
Console.WriteLine("\n->Inc/Dec-rementation");
Console.WriteLine(i++); //i = 1. Post-Incrémentation
Console.WriteLine(++i); //i = 2. Pre-Incrémentation
Console.WriteLine(i--); //i = 1. Post-Decrémentation
Console.WriteLine(--i); //i = 0. Pre-Decrémentation
///////////////////////////////////////
// Structures de contrôle
///////////////////////////////////////
Console.WriteLine("\n->Structures de contrôle");
// Structure conditionnelle
int j = 10;
if (j == 10)
{
Console.WriteLine("Je serai affiché");
}
else if (j > 10)
{
Console.WriteLine("Pas moi");
}
else
{
Console.WriteLine("Moi non plus");
}
// Opérateur ternaire
// Un simple if/else peut s'écrire :
// <condition> ? <valeur si true> : <valeur si false>
string isTrue = (true) ? "True" : "False";
// Boucle while
int fooWhile = 0;
while (fooWhile < 100)
{
// 100 passages, de 0 à 99
fooWhile++;
}
// Boucle Do While
int fooDoWhile = 0;
do
{
// 100 passages, de 0 à 99
fooDoWhile++;
} while (fooDoWhile < 100);
// Boucle for
// Structure : for(<etat_initial>; <condition>; <pas>)
for (int fooFor = 0; fooFor < 10; fooFor++)
{
// 10 passages, de 0 à 9
}
// La boucle foreach
// Structure : foreach(<type_iterateur> <nom_iterateur> in <enumerable>)
// Cette boucle est utilisable sur des objets implémentant IEnumerable ou IEnumerable<T>
// Toutes les collections du framework .NET (Tableaux, Listes, ...) implémentent ces interfaces.
// (Notez que dans l'exemple suivant .ToCharArray() peut être omit car
// string implémente IEnumerable)
foreach (char character in "Hello World".ToCharArray())
{
//Itération sur chaque caractère
}
// La structure Switch Case
// Un switch fonctionne avec les types : byte, short, char et int.
// Les enums sont aussi supportés ainsi que les chaînes de caractères et quelques
// classes spéciales basées sur les types primitifs : Character, Byte, Short et Integer.
int mois = 3;
string moisString;
switch (mois)
{
case 1:
moisString = "Janvier";
break;
case 2:
moisString = "Février";
break;
case 3:
moisString = "Mars";
break;
// Vous pouvez assigner plus d'un 'case' à une action
// Mais vous ne pouvez pas ajouter une action sans 'break' avant un 'case'
// (pour ce faire, il faudrait ajouter explicitement un 'goto case x')
case 6:
case 7:
case 8:
moisString = "C'est l'été!";
break;
default:
moisString = "Un autre mois oO";
break;
}
///////////////////////////////////////
// conversion de type de donnée et transtypage
///////////////////////////////////////
// conversion de string vers int
// lève une exception en cas d'erreur
int.Parse("123"); //retourne la valeur entière de "123"
// TryParse affecte la valeur par défaut du type en cas d'erreur
// dans ce cas : 0
int tryInt;
if (int.TryParse("123", out tryInt)) // La fonction retourne un booléen
Console.WriteLine(tryInt); // => 123
// conversion d'un entier vers une chaîne de caractères
// La classe Convert possède plusieurs méthodes pour faciliter la conversion
Convert.ToString(123);
// ou
tryInt.ToString();
}
///////////////////////////////////////
// CLASSES - voir les définitions à la fin du fichier
///////////////////////////////////////
public static void Classes()
{
// voir les déclarations à la fin du fichier
// Utilisez 'new' pour instancier une classe
Bicycle trek = new Bicycle();
// Appel des méthodes de l'objet
trek.SpeedUp(3); // Il est toujours bon d'utiliser des accesseurs
trek.Cadence = 100;
// Affichage de la valeur de retour d'une méthode.
Console.WriteLine("trek info: " + trek.Info());
// Instanciation d'un nouveau PennyFarthing
PennyFarthing funbike = new PennyFarthing(1, 10);
Console.WriteLine("funbike info: " + funbike.Info());
Console.Read();
}
// POINT D'ENTRÉE - Une application console doit avoir une méthode main comme point d'entrée
public static void Main(string[] args)
{
OtherInterestingFeatures();
}
//
// FONCTIONNALITÉS INTÉRÉSSANTES
//
// SIGNATURE DE METHODE
public // Visibilité
static // Permet un appel direct par la classe (sans instanciation)
int // Type de retour,
MethodSignatures(
int maxCount, // Premier paramètre, de type int
int count = 0, // Valeur par défaut si aucun argument n'est passé
int another = 3,
params string[] otherParams // Capture tous les arguments passés à la méthode
)
{
return -1;
}
// Des méthodes peuvent avoir le même nom tant que leur signature est unique
public static void MethodSignature(string maxCount)
{
}
// TYPE GÉNÉRIQUE
// Les types TKey et TValue sont spécifiés par l'utilisateur lors de l'appel de la fonction
// Cette méthode émule SetDefaut de Python
public static TValue SetDefault<TKey, TValue>(
IDictionary<TKey, TValue> dictionary,
TKey key,
TValue defaultItem)
{
TValue result;
if (!dictionary.TryGetValue(key, out result))
return dictionary[key] = defaultItem;
return result;
}
// Vous pouvez limiter les types autorisés
public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int>
{
// Nous sommes sûrs de pouvoir itérer, car T implémente IEnumerable<int>
foreach (var item in toPrint)
// Item sera de type int
Console.WriteLine(item.ToString());
}
public static void OtherInterestingFeatures()
{
// PARAMÈTERES OPTIONNELS
MethodSignatures(3, 1, 3, "Des", "Paramètres", "En plus");
MethodSignatures(3, another: 3); // affectation explicite, les autres
// paramètres ont la valeur par défaut
// MÉTHODE D'EXTENSION
int i = 3;
i.Print(); // Définit plus bas
// TYPES NULLABLE - idéal pour les interactions avec une base de données ou pour les valeurs de retour
// Tous les types valeurs peuvent être rendus nullable en les suffixant par '?'
// <type>? <nom> = <value>
int? nullable = null; // raccourci pour Nullable<int>
Console.WriteLine("Nullable variable: " + nullable);
bool hasValue = nullable.HasValue; // retourne vrai si la valeur n'est pas null
// ?? est un sucre syntaxique pour spécifier une valeur par défaut
// au cas ou une autre valeur serait nulle
int notNullable = nullable ?? 0; // 0
// VARIABLES IMPLICITEMENT TYPÉES - vous pouvez laisser le compilateur deviner le type d'une variable
var magic = "magic est de type string à la compilation. On a toujours un typage fort !";
// magic = 9; // ne fonctionnera pas car magic est désormais une chaîne de caractères
// TYPES GÉNÉRIQUES
var agenda = new Dictionary<string, string>() {
{"Sarah", "212 555 5555"} // Ajout d'une entrée à notre agenda
};
// Appel de la fonction SetDefault (définie plus haut)
Console.WriteLine(SetDefault<string,string>(agenda, "Shaun", "Pas de numéro")); // => Pas de numéro
// Notez que vous n'avez pas à spécifier TKey et TValue car le compilateur saura les inférer.
Console.WriteLine(SetDefault(agenda, "Sarah", "No Phone")); // => 212 555 5555
// EXPRESSION LAMBDA - permet d'écrire une fonction en tant qu'expression
Func<int, int> square = (x) => x * x; // La dernière expression est la valeur de retour
Console.WriteLine(square(3)); // => 9
// GESTION AUTOMATIQUE DES RESSOURCES - vous permet de manipuler facilement des resources non-managées
// La plus part des objets qui accèdent à des ressources non-managées (handle de fichier, périphérique, etc.)
// implémentent l'interface IDisposable. L'instruction using prend soin
// de libérer les objets IDisposable proprement à votre place.
using (StreamWriter writer = new StreamWriter("log.txt"))
{
writer.WriteLine("Rien à signaler");
// À la fin de cette portée les ressources seront libérées.
// Même si une exception est levée.
}
// BIBLIOTHÈQUE DE TÂCHES PARALLÈLES (TPL)
// http://msdn.microsoft.com/fr-fr/library/dd460717.aspx
var websites = new string[] {
"http://www.google.com", "http://www.reddit.com",
"http://www.shaunmccarthy.com"
};
var responses = new Dictionary<string, string>();
// L'exemple suivant exécutera chaque requête dans un thread séparé,
// et attendra la fin de chacun d'entre eux avant de continuer
Parallel.ForEach(websites,
new ParallelOptions() {MaxDegreeOfParallelism = 3}, // maximum de 3 threads
website =>
{
// Fait quelque chose de long
using (var r = WebRequest.Create(new Uri(website)).GetResponse())
{
responses[website] = r.ContentType;
}
});
// Ceci ne s'exécutera pas tant que les threads n'auront pas fini leur travail
foreach (var key in responses.Keys)
Console.WriteLine("{0}:{1}", key, responses[key]);
// TYPE DYNAMIQUE - idéal pour travailler avec d'autres langages
dynamic student = new ExpandoObject();
student.FirstName = "Mon prénom"; // Pas besoin de définir l'objet
// Vous pouvez même ajouter des méthodes (dans cet exemple : la méthode prend une chaîne de caractères et retourne une chaîne de caractères)
student.Introduce = new Func<string, string>(
(introduceTo) => string.Format("Hey {0}, c'est {1}", student.FirstName, introduceTo));
Console.WriteLine(student.Introduce("Beth"));
// IQUERYABLE<T> - quasiment toutes les collections implémentent cette interface
// ce qui permet d'utiliser des méthodes de style 'Filter' / 'Map' / 'Reduce'
var bikes = new List<Bicycle>();
bikes.Sort(); // Trie le tableau sur place
bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels)); // Trie en se basant sur la propriété Wheels
var result = bikes
.Where(b => b.Wheels > 3) // 'Filter' - enchaînable (retourne un IQueryable du type précédent)
.Where(b => b.IsBroken && b.HasTassles)
.Select(b => b.ToString()); // 'Map' - on retourne le .ToString() de chaque élément filtré,
// le résultat est un IQueryable<string>
var sum = bikes.Sum(b => b.Wheels); // 'Reduce' - fait la somme de tous les Wheels de la liste
// Creation d'une liste d'objet anonymes basés sur des paramètres de la classe Bike
var bikeSummaries = bikes.Select(b=>new { Name = b.Name, IsAwesome = !b.IsBroken && b.HasTassles });
// Le compilateur peut inférer le type de ces objets anonymes, permettant à certains IDE d'effectuer
// des autos-complétion.
foreach (var bikeSummary in bikeSummaries.Where(b => b.IsAwesome))
Console.WriteLine(bikeSummary.Name);
// ASPARALLEL
// C'est ici que les choses se compliquent - un mélange de LINQ et de TPL
var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name);
// La ligne précédente s'exécute en parallèle ! Des threads seront gérés automatiquement
// et les données y seront réparties. Idéal sur de grosses données (et si votre
// machine dispose de plusieurs coeurs)
// LINQ - lie une source de données à des objets IQueryable<T>
// ex : LindToSql => liaison avec une base de données, LinqToXml => liaison avec un document xml
var db = new BikeRespository();
// l'exécution est décalée, ce qui est préférable quand on travaille sur une base données
var filter = db.Bikes.Where(b => b.HasTassles); // pas de requête exécutée
if (42 > 6) // Vous pouvez continuer à affiner la recherche
filter = filter.Where(b => b.IsBroken); // pas de requête exécutée
var query = filter
.OrderBy(b => b.Wheels)
.ThenBy(b => b.Name)
.Select(b => b.Name); // toujours pas de requête exécutée
// Maintenant la requête est exécutée, mais retourne des données uniquement au fil de l'itération
foreach (string bike in query)
Console.WriteLine(result);
}
} // Fin de la classe LearnCSharp
// Il est possible d'inclure plusieurs classes dans un fichier .cs
public static class Extensions
{
// EXTENSION DE FONCTIONS
public static void Print(this object obj)
{
Console.WriteLine(obj.ToString());
}
}
// Syntaxe de déclaration de classe :
// <public/private/protected/internal> class <class name>{
// // champs, constructeurs, fonctions
// // tout est déclaré et implémenté à l'intérieur
// }
public class Bicycle
{
// Propriétés et variable de la classe
public int Cadence // Public : peut être accédé de partout
{
get // get - définit une méthode pour lire la propriété
{
return _cadence;
}
set // set - définit une méthode pour affecter une valeur à la propriété
{
_cadence = value; // 'value' est la valeur passée en argument au setteur
}
}
private int _cadence;
protected virtual int Gear // Protected : accessible depuis la classe et ses classes filles
{
get; // crée une propriété automatique, pas besoin de créer une variable de stockage
set;
}
internal int Wheels // Internal : accessible depuis l'assembly
{
get;
private set; // Il est possible de choisir la portée d'un accesseur
}
int _speed; // Par défaut tout est privé au sein d'une classe : accessible uniquement depuis la classe
// on peut ajouter explicitement le mot clé 'private'
public string Name { get; set; }
// Enum est un type valeur formé par un ensemble de constantes nommées
// C'est simplement une manière de mettre un nom sur une valeur (int par défaut).
// Les types compatibles pour un enum sont : byte, sbyte, short, ushort, int, uint, long et ulong.
// Un enum ne peut pas contenir deux fois la même valeur
public enum BikeBrand
{
AIST,
BMC,
Electra = 42, // il est possible de donner explicitement une valeur
Gitane // 43
}
// Nous avons défini cet enum à l'intérieur de la classe Bicycle, c'est donc un type imbriqué
// Pour le référencer à l'extérieur, il faudra utiliser Bicycle.BikeBrand
public BikeBrand Brand; // Après avoir déclaré notre type enum, on peut créer un champ de ce type
// Les membres statiques appartiennent à une classe plutôt qu'à une instance particulière
// Il est possible d'y accéder sans passer par un objet :
// ex : Console.WriteLine("Bicycles créés : " + Bicycle.bicyclesCreated);
static public int BicyclesCreated = 0;
// Les valeurs en lecture seule sont affectées lors de l'exécution
// Elles ne peuvent être assignées que lors de leur déclaration ou dans un constructeur
readonly bool _hasCardsInSpokes = false; // variable en lecture et privée
// Les constructeurs sont un moyen de créer des objets
// Voici un constructeur par défaut (pas d'arguments)
public Bicycle()
{
this.Gear = 1; // accès aux membres de la classe via le mot clé this
Cadence = 50; // qui est souvent implicite
_speed = 5;
Name = "Bontrager";
Brand = BikeBrand.AIST;
BicyclesCreated++;
}
// Voici un constructeur spécifique (qui prend des arguments)
public Bicycle(int startCadence, int startSpeed, int startGear,
string name, bool hasCardsInSpokes, BikeBrand brand)
: base() // possibilité d'appeler le constructeur de la classe mère (ici Object)
{
Gear = startGear;
Cadence = startCadence;
_speed = startSpeed;
Name = name;
_hasCardsInSpokes = hasCardsInSpokes;
Brand = brand;
}
// Les constructeurs peuvent s'enchaîner
public Bicycle(int startCadence, int startSpeed, BikeBrand brand) :
this(startCadence, startSpeed, 0, "big wheels", true, brand)
{
}
// Syntaxe de méthode :
// <public/private/protected> <type de retour> <nom de methode>(<args>)
// Les classes peuvent implémenter des accesseurs pour leurs champs
// ou implémenter des propriétés (c'est la méthode dominante en C#)
// Les paramètres de méthodes peuvent avoir des valeurs par défaut
// Dans ce cas, la méthode peut être appelée sans arguments
public void SpeedUp(int increment = 1)
{
_speed += increment;
}
public void SlowDown(int decrement = 1)
{
_speed -= decrement;
}
// Les propriétés se chargent de lire/modifier des valeurs
// elles peuvent être en lecture(get), en écriture(set) ou les deux
private bool _hasTassles; // variable privée
public bool HasTassles // propriété publique
{
get { return _hasTassles; }
set { _hasTassles = value; }
}
// Il est possible de définir une propriété automatique sur une ligne
// cette syntaxe créera une variable de stockage automatiquement.
// Il est possible de modifier l'accèsibilité des getter/setter pour limiter leur utilisation
public bool IsBroken { get; private set; }
// La même chose sur plusieurs lignes
public int FrameSize
{
get;
// Notez que seule la classe Bicycle peut changer la valeur de FrameSize
private set;
}
// Méthode qui affiche la valeur des champs de cet objet
public virtual string Info()
{
return "Gear: " + Gear +
" Cadence: " + Cadence +
" Speed: " + _speed +
" Name: " + Name +
" Cards in Spokes: " + (_hasCardsInSpokes ? "yes" : "no") +
"\n------------------------------\n"
;
}
// Les méthodes peuvent aussi être statiques. Utile pour les méthodes d'aide.
public static bool DidWeCreateEnoughBycles()
{
// À l'intérieur d'une méthode statique on ne peut que référencer des membres statiques !
return BicyclesCreated > 9000;
} // Si votre classe n'a que des membres statiques, marquez la comme statique
} // fin de la classe Bicycle
// PennyFarthing est une classe dérivée de Bicycle
class PennyFarthing : Bicycle
{
// Appel au constructeur de la classe mère
public PennyFarthing(int startCadence, int startSpeed) :
base(startCadence, startSpeed, 0, "PennyFarthing", true, BikeBrand.Electra)
{
}
protected override int Gear
{
get
{
return 0;
}
set
{
// Lève une exception
throw new ArgumentException("Impossible de modifier Gear sur un PennyFarthing");
}
}
public override string Info()
{
string result = "PennyFarthing bicycle ";
result += base.ToString(); // Appel à la version de base de cette méthode
return result;
}
}
// Les interfaces contiennent uniquement la signature de leurs membres, sans implémentation.
interface IJumpable
{
void Jump(int meters); // Tous les membres d'interface sont publics par défaut
}
interface IBreakable
{
bool Broken { get; } // Les interfaces peuvent contenir des propriétés,
// des méthodes et des évènements
}
// Une classe ne peut hériter que d'une seule autre classe, mais peut implémenter plusieurs interfaces
class MountainBike : Bicycle, IJumpable, IBreakable
{
int damage = 0;
public void Jump(int meters)
{
damage += meters;
}
public bool Broken
{
get
{
return damage > 100;
}
}
}
/// <summary>
/// Utilisé pour illustrer la connexion à une base donnée dans l'exemple LinqToSql
/// L'approche code first d'EntityFramework est très pratique (un peu comme ActiveRecord de Ruby)
/// http://msdn.microsoft.com/fr-fr/data/jj193542.aspx
/// </summary>
public class BikeRespository : DbSet
{
public BikeRespository()
: base()
{
}
public DbSet<Bicycle> Bikes { get; set; }
}
} // Fin du namespace
```
## Sujets non-abordés
* Flags
* Attribus
* Propriétés statiques
* Exceptions, Abstraction
* ASP.NET (Web Forms/MVC/WebMatrix)
* Winforms
* Windows Presentation Foundation (WPF)
## Lectures Complémentaires
* [DotNetPerls](http://www.dotnetperls.com)
* [C# in Depth](http://manning.com/skeet2)
* [Programming C#](http://shop.oreilly.com/product/0636920024064.do)
* [LINQ](http://shop.oreilly.com/product/9780596519254.do)
* [MSDN Library](http://msdn.microsoft.com/en-us/library/618ayhy6.aspx)
* [ASP.NET MVC Tutorials](http://www.asp.net/mvc/tutorials)
* [ASP.NET Web Matrix Tutorials](http://www.asp.net/web-pages/tutorials)
* [ASP.NET Web Forms Tutorials](http://www.asp.net/web-forms/tutorials)
* [Windows Forms Programming in C#](http://www.amazon.com/Windows-Forms-Programming-Chris-Sells/dp/0321116208)
[Convention de codage C#](http://msdn.microsoft.com/library/vstudio/ff926074)
|