Apprendre la Programmation Orientée Objet avec le langage C#
(avec exercices pratiques et corrigés)
4e édition
Éditions ENI
Avant-propos
Chapitre 1
Introduction à la POO
1. Histoire de la POO15
2. Historique du C#18
Chapitre 2
La conception orientée objet
1. Approche procédurale et décomposition fonctionnelle19
2. La transition vers l'approche objet20
3. Les caractéristiques de la POO21
3.1 L'objet, la classe et la référence21
3.1.1 L'objet21
3.1.2 La classe22
3.1.3 La référence23
3.2 L'encapsulation24
3.3 L'héritage24
3.4 Le polymorphisme26
3.5 L'abstraction27
4. Le développement objet28
4.1 Cahier des charges du logiciel28
4.2 Présentation du cycle en V28
4.3 Modélisation et représentation UML32
4.3.1 Diagrammes de cas d'utilisation35
4.3.2 Diagrammes de classes36
4.3.3 Énumérations42
4.3.4 Diagrammes de séquences43
4.4 Rédaction du code et des tests unitaires45
5. Exercices corrigés46
5.1 Hiérarchie de classes46
5.2 Relations entre objets48
5.3 Agrégation d'objets48
5.4 Diagramme de cas d'utilisation50
5.5 Diagramme de séquences51
Chapitre 3
Introduction à .NET 6 et à VS
1. Introduction53
2. Environnement d'exécution54
3. Le choix des langages55
4. Utiliser plusieurs langages55
5. Une librairie très complète55
6. Un outil de développement complet57
Chapitre 4
Les types du C#
1. « En C#, tout est typé ! »67
2. « Tout le monde hérite de System.Object »72
2.1 Les types Valeurs73
2.2 Les types Références76
2.3 Boxing/unboxing78
2.4 Utilisation des méthodes de System.Object79
2.4.1 Equals80
2.4.2 GetHashCode84
2.4.3 ToString86
2.4.4 Finalize87
2.4.5 Object.Getïype et les opérateurs typeof et is88
2.4.6 object.ReferenceEquals89
2.4.7 Object.MemberwiseClone90
2.5 Le type System.String et son alias string93
3. Exercice corrigé97
3.1 Énoncé97
3.2 Correction97
Chapitre 5
Création d'objets
1. Introduction101
2. Les espaces de noms102
3. Déclaration d'une classe110
3.1 Accessibilité des membres112
3.2 Attributs112
3.2.1 Attributs constants113
3.2.2 Attributs en lecture seule114
3.3 Propriétés116
3.4 Constructeur124
3.4.1 Étapes de la construction d'un objet124
3.4.2 Surcharge de constructeurs126
3.4.3 Constructeurs avec valeurs de paramètres par défaut126
3.4.4 Chaînage de constructeurs127
3.4.5 Les constructeurs de type static128
3.4.6 Les constructeurs de type private129
3.4.7 Les initialiseurs d'objets131
3.5 Destructeur132
3.6 Autre utilisation de using134
3.7 Le mot-clé this et ses vertus135
3.8 Méthodes138
3.8.1 Déclaration139
3.8.2 Passage par valeur et passage par référence142
3.9 Mécanisme des exceptions159
3.9.1 Présentation159
3.9.2 Principe de fonctionnement des exceptions160
3.9.3 Prise en charge de plusieurs exceptions169
3.9.4 try ... catch ... finally et using170
3.10 Surcharge des méthodes172
3.11 Exercice174
3.11.1 Énoncé174
3.11.2 Conseils175
3.11.3Correction175
4. Les interfaces178
4.1 Introduction178
4.2 Le contrat178
4.3 Déclaration d'une interface179
4.4 Implémentation181
4.5 Visual Studio et les interfaces183
4.6 Représentation UML d'une interface186
4.7 Interfaces et polymorphisme187
4.8 Exercice188
4.8.1 Énoncé188
4.8.2 Conseils188
4.8.3 Correction191
4.9 Les interfaces du .NET194
5. Association, composition et agrégation196
5.1 Les tableaux204
5.2 Les collections :212
5.2.1 List<> et LinkedList<>213
5.2.2 Queue<T> et Stack<T>216
5.2.3 Dictionary<TKey, TValue>217
5.2.4 Les énumérateurs217
5.2.5 La magie du yield219
5.3 Exercice220
5.3.1 Énoncé220
5.3.2 Correction222
6. Les classes imbriquées223
7. Les structures225
7.1 Déclaration d'une structure226
7.2 Instanciation d'une structure228
8. Les classes partielles230
9. Les méthodes partielles231
10. Les indexeurs233
11. Surcharge d'opérateurs237
12. Fonctions locales240
13. Les objets « gourmands » en références faibles241
14. Les objets « dynamics »243
15. Les « Tuple » et « ValueTuple »244
16. Les records245
16.1 Introduction245
16.2 Déclaration complète246
16.3 Déclaration simplifiée247
16.4 Comparaison de records249
16.5 Déconstruction d'un record251
16.6 Mutation d'un record251
Chapitre 6
Héritage et polymorphisme
1. Comprendre l'héritage253
2. Codage de la classe de base et de son héritière254
2.1 Interdire l'héritage254
2.2 Définir les membres héritables255
2.3 Codage de l'héritage255
2.4 Exploitation d'une classe héritière256
3. Communication entre classe de base et classe héritière257
3.1 Les constructeurs257
3.2 Accès aux membres de base depuis l'héritier260
3.3 Masquage ou substitution de membres hérités262
3.3.1 Codage du masquage264
3.3.2 Codage de la substitution266
4. Exercice267
4.1 Énoncé267
4.2 Corrigé268
5. Les classes abstraites269
6. Les méthodes d'extension271
7. Le polymorphisme274
7.1 Comprendre le polymorphisme274
7.2 Exploitation du polymorphisme275
7.3 Les opérateurs is, as et ()275
Chapitre 7
Communication entre objets
1. L'événementiel : être à l'écoute279
2. Le pattern Observateur280
3. La solution C# : delegate et event284
3.1 Utilisation du delegate dans le design pattern Observateur287
3.2 Utilisation d'un event290
3.3 Comment accompagner l'event de données293
3.4 Les génériques en renfort pour encore simplifier295
3.5 Les expressions lambda296
3.6 Exemple d'utilisation d'event301
4. Appels synchrones, appels asynchrones309
5. Exercice311
5.1 Énoncé311
5.2 Conseils pour la réalisation312
5.3 Correction312
6. Des messages entre les classes316
Chapitre 8
Le multithreading
1. Introduction317
2. Comprendre le multithreading318
3. Multithreading et .NET321
4. Implémentation en C#322
4.1 Utilisation d'un BackgroundWorker322
4.1.1 Communication du thread principal vers le thread secondaire324
4.1.2 Abandon du thread secondaire depuis le thread principal325
4.1.3 Communication du thread secondaire vers le thread principal326
4.1.4 Communication en fin de traitement du thread secondaire326
4.1.5 Exemple de code327
4.2 Utilisation du pool de threads créé par .NET329
4.3 Gestion « manuelle » avec Thread/ParameterizedThreadStart331
5. Synchronisation entre threads336
5.1 Nécessité de la synchronisation336
5.2 Le mot-clé lock338
5.3 La classe Monitor339
5.4 La classe Mutex340
5.5 La classe Semaphore341
6. Communication entre threads342
6.1 Join342
6.2 Les synchronization events343
6.3 Communication entre threads secondaires et IHM350
6.4 Exercice353
6.4.1 Énoncé353
6.4.2 Correction353
7. La programmation asynchrone357
7.1 Les « Task »357
7.2 async et await359
7.3 Le mot-clé async360
7.4 Contenu d'une méthode async360
7.5 Preuve à l'appui360
7.6 Retours possibles d'une méthode async362
Chapitre 9
P-Invoke
1. Introduction365
1.1 Rappel sur les DLL non managées366
1.2 P-Invoke et son Marshal366
2. Le cas simple367
2.1 Déclaration et appel368
2.2 Réglage de Visual Studio pour la mise au point370
3. Appel avec paramètres et retour de fonction371
4. Traitement avec des chaînes de caractères373
4.1 Encodage des caractères373
4.2 Encodage des chaînes374
4.3 Transmission des chaînes375
5. Echange de tableaux378
5.1 Du C# au C/C+ +378
5.2 Du C# au C/C+ + puis retour au C#380
6. Partage de structures381
6.1 Déclaration des structures381
6.2 Utilisation des structures383
7. Les directives [In] et [Out]388
8. Réalisation d'un wrapper392
8.1 Une région « NativeMethods »393
8.2 Stockage des informations de la DLL native394
8.3 Instanciation de DLL native395
8.4 Méthodes d'utilisation de la DLL managée depuis le wrapper397
8.5 Utilisation du wrapper398
9. Exercice399
9.1 Énoncé399
9.2 Correction400
Chapitre 10
Les tests
1. Introduction403
2. Environnement d'exécution des tests unitaires405
3. Le projet de tests unitaires408
4. La classe de tests409
5. Contenu d'une méthode de test410
6. Traitements de préparation et de nettoyage413
7. DynamicData et source de données417
8. Automatisation des tests à la compilation422
9. Automatisation des tests en dehors de Visual Studio423
10. CodedUI425
11. Exercice426
11.1 Énoncé426
11.2 Correction426
12. Simulation par stub ou par shim428
Chapitre 11
Traçage et instrumentation des applications
1. Présentation431
2. Des objets de mise au point432
2.1 System.Diagnostics.Debug432
2.2 System.Diagnostics.Trace435
2.3 System.Diagnostics.TraceSource436
3. Principe de fonctionnement des écouteurs437
4. Comportement dynamique439
5. Mesurer le temps passé443
6. Exercice446
6.1 Énoncé446
6.2 Correction446
Chapitre 12
La réflexion
1. Introduction449
2. Mais pour quoi faire ?450
3. Introspection d'une classe C#452
3.1 Introspection « manuelle »455
3.2 Introspection « logicielle »458
3.2.1 Découverte et instanciation458
3.2.2 Découverte et utilisation des propriétés461
3.2.3 Découverte et utilisation des méthodes463
3.3 Exercice466
3.3.1 Énoncé466
3.3.2 Quelques conseils466
3.3.3 Correction466
4. Chargement dynamique d'un objet implémentant une interface469
4.1 Création d'une interface « plug-in »470
4.2 Écriture d'un plug-in471
4.3 L'application supportant les plug-ins473
4.4 Exercice475
4.4.1 Énoncé475
4.4.2 Correction475
5. Décompilation et obfuscation477
6. Conclusion483
Chapitre 13
Gestion des données
1. Introduction485
2. LINQ486
2.1 Qu'est-ce que c'est ?486
2.2 Les deux syntaxes LINQ487
2.2.1 La syntaxe « développeur SQL »487
2.2.2 La syntaxe « développeur C# »489
2.3 Requêtes et filtres489
2.4 Quelques calculs492
2.5 Regroupement des résultats494
2.6 Les jointures496
2.7 Exercice498
2.7.1 Énoncé498
2.7.2 Solution499
3. Persistance des données en XML506
3.1 Rappels sur le XML507
3.2 XML et .NET509
3.2.1 Sérialisation/désérialisation d'un modèle de données509
3.2.2 Les décorations de sérialisation XML509
3.2.3 XmlSerializer : écrire et lire513
3.3 XSD.EXE, un outil de conversion516
3.4 Exercice518
3.4.1 Énoncé518
3.4.2 Correction518
3.5 LINQ to XML520
3.5.1 Lecture521
3.5.2 Écriture522
3.5.3 Interrogations524
3.6 Exercice524
3.6.1 Énoncé524
3.6.2 Correction524
4. Persistance dans des bases de données avec ADO.NET526
4.1 Présentation526
4.2 Les termes utilisés526
4.3 Les modules ADO.NET527
4.4 Notre environnement d'apprentissage528
4.5 ADO en mode connecté532
4.5.1 Les fournisseurs de données en .NET532
4.5.2 Se connecter avec DbConnection533
4.5.3 Envoyer des requêtes avec DbCommand537
4.5.4 Lire des enregistrements avec DbDataReader543
4.6 Exercice546
4.6.1 Énoncé546
4.6.2 Correction546
4.7 ADO en mode déconnecté548
4.7.1 La classe DataSet548
4.7.2 Le DataSet typé551
4.7.3 Persistance du DataSet en XML559
4.7.4 LINO to DataSet561
4.7.5 Intégrité référentielle562
4.8 DbAdapter : jonction des deux modes569
4.8.1 Lecture de la source570
4.8.2 Mise à jour de la source573
5. Entity Framework580
5.1 Présentation de l'Entity Data Model581
5.2 Création d'un EDM depuis une base de données582
5.3 DbContext588
5.4 LINQ to Entities594
5.5 Mise à jour de la source596
5.6 Création d'un EDM depuis un modèle600
5.7 Exercice612
5.7.1 Présentation du binding612
5.7.2 Énoncé613
5.7.3 Correction613
6. Conclusion614
Chapitre 14
WPF MWM et le toolkit Microsoft
1. Présentation615
2. Historique des API616
3. C# et XAML Développeur et Graphiste617
4. Balises et Attributs pour Objets et Propriétés617
5. Utilisation basique de WPF622
6. Utilisation des layout626
7. Récupération des informations SANS le binding633
8. Introduction au binding639
8.1 Le DataContext639
8.2 L'interface INotifyPropertyChange642
8.3 Les convertisseurs645
8.4 Exercice648
8.5 Binding de commandes649
9. Le modèle de conception MVVM656
9.1 Objectifs656
9.2 Les dépendances657
9.3 Mise en application658
10. Présentation de MVVM Toolkit669
10.1 La classe Observable669
10.2 La classe ObservableValidator671
10.3 Messenger672
10.4 L'injection de dépendances675
Index681