From 74c24933a12bfa3c6a4ec3c69f4ebf5c671bf186 Mon Sep 17 00:00:00 2001 From: marcchevaldonne Date: Thu, 15 Sep 2022 16:00:58 +0200 Subject: [PATCH] update to .NET6 --- p02_Fondamentaux/ex_003_001_Main/Program.cs | 31 ++ .../ex_003_001_Main/ex_003_001_Main.csproj | 12 + .../ex_003_002_Main_HelloWorld/Program.cs | 27 ++ .../ex_003_002_Main_HelloWorld.csproj | 12 + .../ex_003_003_Main_arguments/Program.cs | 41 +++ .../Properties/launchSettings.json | 8 + .../ex_003_003_Main_arguments/ReadMe.md | 19 ++ .../ex_003_003_Main_arguments.csproj | 12 + .../ex_003_004_Console/Program.cs | 103 +++++++ .../ex_003_004_Console.csproj | 12 + .../ex_004_001_TypesNumeriques/Program.cs | 79 +++++ .../ex_004_001_TypesNumeriques.csproj | 12 + p02_Fondamentaux/ex_004_002_Math/Program.cs | 99 +++++++ .../ex_004_002_Math/ex_004_002_Math.csproj | 12 + p02_Fondamentaux/ex_004_003_Random/Program.cs | 47 +++ .../ex_004_003_Random.csproj | 12 + .../ex_004_004_TypeBool/Program.cs | 31 ++ .../ex_004_004_TypeBool.csproj | 12 + .../ex_004_005_TypeChar/Program.cs | 76 +++++ .../ex_004_005_TypeChar.csproj | 12 + .../Program.cs | 72 +++++ .../ex_004_006_TimeSpan_et_DateTime.csproj | 12 + .../ex_004_007_DureeDeVie/Program.cs | 41 +++ .../ex_004_007_DureeDeVie.csproj | 12 + p02_Fondamentaux/ex_004_008_var/Program.cs | 29 ++ .../ex_004_008_var/ex_004_008_var.csproj | 12 + .../ex_004_009_Tuple/Program.CSharp7.cs | 92 ++++++ p02_Fondamentaux/ex_004_009_Tuple/Program.cs | 61 ++++ .../ex_004_009_Tuple/ex_004_009_Tuple.csproj | 15 + .../ex_004_010_GuidStruct/Program.cs | 37 +++ .../ex_004_010_GuidStruct.csproj | 12 + .../ex_005_001_tableaux/Program.cs | 115 ++++++++ .../ex_005_001_tableaux.csproj | 12 + .../ex_005_002_copie_de_tableaux/Program.cs | 124 ++++++++ .../ex_005_002_copie_de_tableaux.csproj | 12 + .../Program.cs | 70 +++++ ...ex_005_003_tableaux_multiDimensions.csproj | 12 + p02_Fondamentaux/ex_006_001_string/Program.cs | 182 ++++++++++++ .../ex_006_001_string.csproj | 12 + .../ex_006_002_StringBuilder/Program.cs | 75 +++++ .../ex_006_002_StringBuilder.csproj | 12 + p02_Fondamentaux/ex_007_001_enum/Program.cs | 108 +++++++ .../ex_007_001_enum/ex_007_001_enum.csproj | 12 + .../ex_008_001_if_else/Program.cs | 78 +++++ .../ex_008_001_if_else.csproj | 12 + p02_Fondamentaux/ex_008_002_switch/Program.cs | 77 +++++ .../ex_008_002_switch.csproj | 12 + .../ex_008_003_ternary_operator/Program.cs | 37 +++ .../ex_008_003_ternary_operator.csproj | 12 + .../ex_008_004_null_operators/Program.cs | 74 +++++ .../ex_008_004_null_operators.csproj | 12 + .../ex_008_005_pattern_matching/Program.cs | 149 ++++++++++ .../ex_008_005_pattern_matching.csproj | 6 + .../ex_009_001_bouclesIteratives/Program.cs | 74 +++++ .../ex_009_001_bouclesIteratives.csproj | 12 + .../Program.cs | 183 ++++++++++++ ...10_001_methodParametersAndModifiers.csproj | 12 + .../ex_010_002_optionalParameters/Program.cs | 45 +++ .../ex_010_002_optionalParameters.csproj | 12 + .../Program.cs | 122 ++++++++ ...003_interets_des_optionalparameters.csproj | 12 + .../ex_012_001_nullableTypes/Program.cs | 51 ++++ .../ex_012_001_nullableTypes.csproj | 12 + .../Program.cs | 174 +++++++++++ ..._013_001_FormattingParsingNumEtBool.csproj | 12 + .../Program.cs | 55 ++++ ...x_013_002_FormattingParsingDateTime.csproj | 12 + .../Program.cs | 63 ++++ ..._014_001_namespace_et_nomDUneClasse.csproj | 12 + p03_POO/ex_014_002_typesImbriques/Program.cs | 50 ++++ .../ex_014_002_typesImbriques.csproj | 12 + .../Program.cs | 70 +++++ ...ex_014_003_ClasseChampInitialiseurs.csproj | 12 + p03_POO/ex_014_004_constructeurs/Program.cs | 46 +++ .../ex_014_004_constructeurs.csproj | 12 + p03_POO/ex_014_005_methodes/Program.cs | 58 ++++ .../ex_014_005_methodes.csproj | 12 + p03_POO/ex_014_006_object_ToString/Program.cs | 91 ++++++ .../ex_014_006_object_ToString.csproj | 12 + .../Program.cs | 93 ++++++ ...x_014_007_expression_bodied_methods.csproj | 12 + p03_POO/ex_014_008_deconstruction/Program.cs | 66 +++++ .../ex_014_008_deconstruction.csproj | 6 + p03_POO/ex_015_001_static/Program.cs | 114 ++++++++ .../ex_015_001_static.csproj | 12 + .../ex_015_002_ordreAppelStatic/Program.cs | 58 ++++ .../ex_015_002_ordreAppelStatic.csproj | 12 + p03_POO/ex_015_003_singleton/Program.cs | 47 +++ .../ex_015_003_singleton.csproj | 12 + p03_POO/ex_015_004_using_static/Program.cs | 126 ++++++++ .../ex_015_004_using_static.csproj | 12 + .../Program.cs | 117 ++++++++ .../ex_016_001_getters_setters_methods.csproj | 12 + p03_POO/ex_016_002_properties/Program.cs | 141 +++++++++ .../ex_016_002_properties.csproj | 12 + p03_POO/ex_016_003_indexers/Program.cs | 232 +++++++++++++++ .../ex_016_003_indexers.csproj | 12 + p03_POO/ex_016_004_readonly/Program.cs | 69 +++++ .../ex_016_004_readonly.csproj | 12 + .../MaClasse.QqsDétails.cs | 23 ++ p03_POO/ex_016_005_partial/MaClasse.cs | 33 +++ p03_POO/ex_016_005_partial/Program.cs | 27 ++ .../ex_016_005_partial.csproj | 12 + p03_POO/ex_016_006_local_functions/Program.cs | 139 +++++++++ .../ex_016_006_local_functions.csproj | 6 + .../ex_017_001_heritage_syntaxe/Program.cs | 87 ++++++ .../ex_017_001_heritage_syntaxe.csproj | 12 + .../Program.cs | 111 +++++++ .../ex_017_002_redefinitionDeMethodes.csproj | 12 + .../Program.cs | 67 +++++ ...017_003_initialiseurs_constructeurs.csproj | 12 + p03_POO/ex_017_004_casting/Program.cs | 88 ++++++ .../ex_017_004_casting.csproj | 12 + p03_POO/ex_018_001_polymorphisme/Program.cs | 157 ++++++++++ .../ex_018_001_polymorphisme.csproj | 12 + p03_POO/ex_018_002_abstract/Program.cs | 146 +++++++++ .../ex_018_002_abstract.csproj | 12 + p03_POO/ex_019_001_interfaces/Program.cs | 190 ++++++++++++ .../ex_019_001_interfaces.csproj | 12 + p03_POO/ex_020_001_structures/Program.cs | 114 ++++++++ .../ex_020_001_structures.csproj | 12 + .../ex_021_001_patternComposite/Program.cs | 101 +++++++ .../ex_021_001_patternComposite.csproj | 12 + p03_POO/ex_021_002_patternStrategy/Program.cs | 56 ++++ .../ex_021_002_patternStrategy.csproj | 12 + .../ex_022_001_Generics_def_du_pb/Program.cs | 183 ++++++++++++ .../ex_022_001_Generics_def_du_pb.csproj | 12 + .../Program.cs | 128 ++++++++ ...22_002_Generics_EtPourquoiPasObject.csproj | 12 + .../ex_022_003_Generics_syntaxe/Program.cs | 119 ++++++++ .../ex_022_003_Generics_syntaxe.csproj | 12 + .../ex_022_004_Generics_default/Program.cs | 115 ++++++++ .../ex_022_004_Generics_default.csproj | 12 + .../Program.cs | 123 ++++++++ .../ex_022_005_Generics_constraints.csproj | 12 + .../Program.cs | 131 +++++++++ .../ex_022_006_Generics_constraints2.csproj | 12 + .../Program.cs | 197 +++++++++++++ .../ex_022_007_Generics_subclassing.csproj | 12 + .../ex_022_008_CovarianceClasses/Program.cs | 149 ++++++++++ .../ex_022_008_CovarianceClasses.csproj | 12 + .../Program.cs | 46 +++ .../ex_022_009_CovarianceInterfaces.csproj | 12 + .../ex_023_001_IEnumerator_ex1/Program.cs | 46 +++ .../ex_023_001_IEnumerator_ex1.csproj | 12 + .../ex_023_002_IEnumerator_ex2/Program.cs | 27 ++ .../StrangeCollection.cs | 36 +++ .../ex_023_002_IEnumerator_ex2.csproj | 12 + .../ex_023_003_IEnumerator_ex3/Program.cs | 27 ++ .../StrangeCollection.cs | 74 +++++ .../ex_023_003_IEnumerator_ex3.csproj | 12 + .../ex_023_004_ArrayClass/Program.cs | 114 ++++++++ .../ex_023_004_ArrayClass.csproj | 12 + .../ex_023_005_Queue/Program.cs | 51 ++++ .../ex_023_005_Queue/ex_023_005_Queue.csproj | 12 + .../ex_023_006_Stack/Program.cs | 49 ++++ .../ex_023_006_Stack/ex_023_006_Stack.csproj | 12 + .../ex_023_007_LinkedList/Program.cs | 60 ++++ .../ex_023_007_LinkedList.csproj | 12 + p04_AdvancedCSharp/ex_023_008_List/Program.cs | 89 ++++++ .../ex_023_008_List/ex_023_008_List.csproj | 12 + .../Program.cs | 105 +++++++ .../ex_023_009_HashSet_and_SortedSet.csproj | 12 + .../Nounours.cs | 83 ++++++ .../Program.cs | 31 ++ .../VieuxNounours.cs | 36 +++ ...3_010_EqualityProtocoleOnReferences.csproj | 12 + .../Nounours.cs | 84 ++++++ .../Program.cs | 31 ++ .../VieuxNounours.cs | 36 +++ ...x_023_011_EqualityProtocoleOnValues.csproj | 12 + .../Nounours.EqualityComparer.cs | 48 +++ .../ex_023_012_EqualityComparer/Nounours.cs | 97 ++++++ .../NounoursNbPoilsEqualityComparer.cs | 31 ++ .../ex_023_012_EqualityComparer/Program.cs | 30 ++ .../ex_023_012_EqualityComparer.csproj | 12 + .../Nounours.NbPoilsComparer.cs | 43 +++ .../Nounours.cs | 98 +++++++ .../NounoursDateComparer.cs | 26 ++ .../Program.cs | 53 ++++ ...ex_023_013_OrderComparisonProtocole.csproj | 12 + .../ex_023_014_Dictionary/Program.cs | 169 +++++++++++ .../ex_023_014_Dictionary.csproj | 12 + .../Nounours.cs | 92 ++++++ .../NounoursNbPoilsEqualityComparer.cs | 28 ++ .../Program.cs | 150 ++++++++++ .../VieuxNounours.cs | 43 +++ .../ex_023_015_DictionaryCustomType.csproj | 12 + .../ex_023_016_ReadOnlyCollection/MonLit.cs | 130 +++++++++ .../ex_023_016_ReadOnlyCollection/MonLit2.cs | 131 +++++++++ .../ex_023_016_ReadOnlyCollection/Nounours.cs | 53 ++++ .../Nounours2.cs | 53 ++++ .../ex_023_016_ReadOnlyCollection/Program.cs | 72 +++++ .../ex_023_016_ReadOnlyCollection.csproj | 12 + .../INounours.cs | 43 +++ .../MonLit.cs | 91 ++++++ .../Nounours.cs | 54 ++++ ..._017_Deep_Read_only_collections_dll.csproj | 11 + .../Program.cs | 121 ++++++++ ..._017_Deep_Read_only_collections_exe.csproj | 15 + .../ex_023_018_ReadOnlyDictionaries/MonLit.cs | 54 ++++ .../Nounours.cs | 99 +++++++ .../Program.cs | 49 ++++ .../ex_023_018_ReadOnlyDictionaries.csproj | 12 + .../INounours.cs | 43 +++ .../MonLit.cs | 73 +++++ .../Nounours.cs | 102 +++++++ ...9_ReadOnlyDictionary_and_values_dll.csproj | 11 + .../Program.cs | 70 +++++ ...9_ReadOnlyDictionary_and_values_exe.csproj | 15 + .../ex_024_001_exceptions_Contexte/Program.cs | 35 +++ .../ex_024_001_exceptions_Contexte.csproj | 12 + p05_More_dotNet/ex_024_002_parse/Program.cs | 106 +++++++ .../ex_024_002_parse/ex_024_002_parse.csproj | 12 + .../ex_024_003_exceptions/Program.cs | 75 +++++ .../ex_024_003_exceptions.csproj | 12 + .../Program.cs | 109 +++++++ .../ex_024_004_propagation_exceptions.csproj | 12 + .../Program.cs | 60 ++++ ...x_024_005_exceptions_personnalisees.csproj | 12 + .../ex_025_001_DebugTrace/Program.cs | 79 +++++ .../ex_025_001_DebugTrace.csproj | 12 + .../Carré.cs | 21 ++ .../ex_028_001_intro_avec_interfaces/Cube.cs | 21 ++ .../Droite.cs | 39 +++ .../IModifieur.cs | 18 ++ .../Program.cs | 38 +++ .../ex_028_001_intro_avec_interfaces.csproj | 12 + .../ex_028_002_intro_avec_delegate/Droite.cs | 51 ++++ .../MaClasseDeMaths.cs | 56 ++++ .../ex_028_002_intro_avec_delegate/Program.cs | 131 +++++++++ .../ex_028_002_intro_avec_delegate.csproj | 12 + .../Carré.cs | 21 ++ .../ex_028_003_interface_as_parameter/Cube.cs | 21 ++ .../Droite.cs | 39 +++ .../IModifieur.cs | 18 ++ .../Program.cs | 67 +++++ .../ex_028_003_interface_as_parameter.csproj | 12 + .../Droite.cs | 51 ++++ .../MaClasseDeMaths.cs | 56 ++++ .../Program.cs | 131 +++++++++ .../ex_028_004_delegate_as_parameter.csproj | 12 + .../ex_028_005_nested_delegate/Droite.cs | 51 ++++ .../MaClasseDeMaths.cs | 63 ++++ .../ex_028_005_nested_delegate/Program.cs | 125 ++++++++ .../ex_028_005_nested_delegate.csproj | 12 + .../Carré.cs | 21 ++ .../ex_028_006_Strategy_et_interface/Cube.cs | 21 ++ .../Droite.cs | 39 +++ .../IModifieur.cs | 18 ++ .../Program.cs | 63 ++++ .../ex_028_006_Strategy_et_interface.csproj | 12 + .../Droite.cs | 51 ++++ .../MaClasseDeMaths.cs | 56 ++++ .../Program.cs | 74 +++++ ...ex_028_007_delegate_versus_Strategy.csproj | 12 + .../AffichePourcentage.cs | 26 ++ .../ClasseQuiFaitDuGrosTravail.cs | 47 +++ .../ClearProgression.cs | 23 ++ .../IProgression.cs | 21 ++ .../Program.cs | 62 ++++ .../ProgressBar.cs | 29 ++ .../ex_028_008_multicast_et_interfaces.csproj | 12 + .../GrosTravail.cs | 64 ++++ .../ex_028_009_multicast_delegate/Program.cs | 81 +++++ .../ex_028_009_multicast_delegate.csproj | 12 + .../GrosTravail.cs | 65 +++++ .../Program.cs | 70 +++++ ...010_multicast_delegate_return_value.csproj | 12 + .../Broadcaster.cs | 38 +++ .../ConcreteSubscriber.cs | 37 +++ .../ISubscriber.cs | 18 ++ .../InfoSportBroadcaster.cs | 57 ++++ .../Program.cs | 41 +++ .../ex_028_011_Broadcaster_Subscriber.csproj | 12 + .../Broadcaster.cs | 77 +++++ .../Program.cs | 52 ++++ .../Subscriber.cs | 87 ++++++ ...012_delegate_Broadcaster_Subscriber.csproj | 12 + .../ex_028_013_Predicate/Program.cs | 120 ++++++++ .../ex_028_013_Predicate.csproj | 12 + .../ex_028_014_Func/Droite.cs | 51 ++++ .../ex_028_014_Func/MaClasseDeMaths.cs | 55 ++++ .../ex_028_014_Func/Program.cs | 85 ++++++ .../ex_028_014_Func/ex_028_014_Func.csproj | 12 + .../ex_028_015_Action/GrosTravail.cs | 60 ++++ .../ex_028_015_Action/Program.cs | 99 +++++++ .../ex_028_015_Action.csproj | 12 + .../Broadcaster.cs | 76 +++++ .../Program.cs | 50 ++++ .../Subscriber.cs | 90 ++++++ ...29_001_event_Broadcaster_Subscriber.csproj | 12 + .../Broadcaster.cs | 92 ++++++ .../InfoChangedEventArgs.cs | 55 ++++ .../Program.cs | 37 +++ .../Subscriber.cs | 70 +++++ .../ex_029_002_event_standard_pattern.csproj | 12 + .../ex_030_001_anonymousMethods/Program.cs | 64 ++++ .../ex_030_001_anonymousMethods.csproj | 12 + .../ex_030_002_lambdaExpressions/Program.cs | 60 ++++ .../ex_030_002_lambdaExpressions.csproj | 12 + .../GrosTravail.cs | 64 ++++ .../ex_030_003_lambdaExpressions/Program.cs | 56 ++++ .../ex_030_003_lambdaExpressions.csproj | 12 + .../ex_031_001_decouverteDeLINQ/Nounours.cs | 81 +++++ .../ex_031_001_decouverteDeLINQ/Program.cs | 276 ++++++++++++++++++ .../ex_031_001_decouverteDeLINQ.csproj | 12 + .../ex_031_002_extensionMethods/Program.cs | 69 +++++ .../ex_031_002_extensionMethods.csproj | 12 + .../ex_031_003_anonymousTypes/Program.cs | 71 +++++ .../ex_031_003_anonymousTypes.csproj | 12 + .../ex_031_004_LINQ_intro/Program.cs | 132 +++++++++ .../ex_031_004_LINQ_intro.csproj | 12 + .../Nounours.cs | 36 +++ .../Program.cs | 62 ++++ .../ex_031_005_LINQ_deferredExecution.csproj | 12 + .../ex_031_005_LINQ_operators/Program.cs | 14 + .../ex_031_006_LINQ_filtering/Nounours.cs | 72 +++++ .../ex_031_006_LINQ_filtering/Program.cs | 113 +++++++ .../ex_031_006_LINQ_filtering.csproj | 12 + .../ex_031_007_LINQ_ordering/Nounours.cs | 79 +++++ .../NounoursDateComparer.cs | 26 ++ .../ex_031_007_LINQ_ordering/Program.cs | 116 ++++++++ .../ex_031_007_LINQ_ordering.csproj | 12 + .../ex_031_008_LINQ_projecting/Nounours.cs | 79 +++++ .../ex_031_008_LINQ_projecting/Program.cs | 141 +++++++++ .../ex_031_008_LINQ_projecting.csproj | 12 + .../Nounours.cs | 79 +++++ .../Program.cs | 129 ++++++++ .../ex_031_009_LINQ_element_operators.csproj | 12 + .../Nounours.cs | 79 +++++ .../Program.cs | 80 +++++ ...ex_031_010_LINQ_aggregation_methods.csproj | 12 + .../ex_031_011_LINQ_grouping/Nounours.cs | 79 +++++ .../ex_031_011_LINQ_grouping/Program.cs | 99 +++++++ .../ex_031_011_LINQ_grouping.csproj | 12 + .../ex_031_012_LINQ_joining/Enfant.cs | 34 +++ .../ex_031_012_LINQ_joining/Nounours.cs | 79 +++++ .../ex_031_012_LINQ_joining/Program.cs | 72 +++++ .../ex_031_012_LINQ_joining.csproj | 12 + .../ex_031_013_LINQ_set_operators/Program.cs | 73 +++++ .../ex_031_013_LINQ_set_operators.csproj | 12 + .../ex_031_014_LINQ_quantifiers/Program.cs | 53 ++++ .../ex_031_014_LINQ_quantifiers.csproj | 12 + .../Program.cs | 39 +++ .../ex_031_015_LINQ_generation_methods.csproj | 12 + .../Nounours.cs | 79 +++++ .../Program.cs | 66 +++++ .../ex_031_016_LINQ_conversion_methods.csproj | 12 + .../ex_036_001_Reflection/README.md | 57 ++++ .../Solution/Applications/Program.cs | 76 +++++ .../Applications/ex_036_001_Reflection.csproj | 34 +++ .../Solution/ChatChienOiseauDll/Chat.cs | 25 ++ .../Solution/ChatChienOiseauDll/Chien.cs | 25 ++ .../Solution/ChatChienOiseauDll/Oiseau.cs | 31 ++ .../ex_036_001_ChatChienOiseau.csproj | 34 +++ .../Solution/MammifereDll/Mammifere.cs | 30 ++ .../MammifereDll/ex_036_001_Mammifere.csproj | 31 ++ .../ex_036.0.6_ChatChienOiseau.deps.json | 36 +++ .../net6.0/ex_036.0.6_ChatChienOiseau.dll | Bin 0 -> 4608 bytes .../plugin/net6.0/ex_036.0.6_Mammifere.dll | Bin 0 -> 4096 bytes .../Program.cs | 106 +++++++ ...7_001_File_and_Directory_management.csproj | 12 + .../ex_037_002_FileStream/Program.cs | 130 +++++++++ .../ex_037_002_FileStream.csproj | 12 + .../exemple_filestream.txt | 8 + .../ex_037_002_FileStream/fichier.txt | 1 + .../Program.cs | 115 ++++++++ .../ex_037_003_TextReader_TextWriter.csproj | 12 + .../Nounours.cs | 91 ++++++ .../Program.cs | 64 ++++ ...x_037_004_BinaryReader_BinaryWriter.csproj | 12 + .../Nounours.cs | 91 ++++++ .../ex_037_005_XmlReader_XmlWriter/Program.cs | 103 +++++++ .../XML/nounours.xml | 5 + .../ex_037_005_XmlReader_XmlWriter.csproj | 12 + .../Nounours.cs | 136 +++++++++ .../Program.cs | 141 +++++++++ .../XML/.gitignore | 4 + ...38_001_DataContractSerializer_bases.csproj | 16 + .../Animal.cs | 39 +++ .../Chat.cs | 32 ++ .../Chien.cs | 31 ++ .../Oiseau.cs | 31 ++ .../Program.cs | 128 ++++++++ .../XML/.gitignore | 4 + ...ex_038_002_DataContract_subclassing.csproj | 15 + .../Album.cs | 47 +++ .../Artiste.cs | 47 +++ .../Morceau.cs | 41 +++ .../Program.cs | 90 ++++++ .../XML/.gitignore | 4 + ...8_003_DataContract_ObjectReferences.csproj | 15 + .../Animal.cs | 39 +++ .../AnimalList.cs | 33 +++ .../Chat.cs | 32 ++ .../Chien.cs | 31 ++ .../Ménagerie.cs | 53 ++++ .../Oiseau.cs | 31 ++ .../Program.cs | 89 ++++++ .../XML/.gitignore | 4 + ...ex_038_004_DataContract_Collections.csproj | 15 + .../ex_038_005_DataContract_Hooks/Animal.cs | 53 ++++ .../ex_038_005_DataContract_Hooks/Animal2.cs | 67 +++++ .../ex_038_005_DataContract_Hooks/Program.cs | 77 +++++ .../XML/.gitignore | 4 + .../ex_038_005_DataContract_Hooks.csproj | 15 + .../Nounours.cs | 133 +++++++++ .../ex_038_006_Binary_Serializable/Program.cs | 86 ++++++ .../ex_038_006_Binary_Serializable.csproj | 8 + .../result/.gitignore | 4 + .../ex_038_007_XmlSerializer/Animal.cs | 67 +++++ .../ex_038_007_XmlSerializer/AnimalList.cs | 33 +++ .../ex_038_007_XmlSerializer/Chat.cs | 37 +++ .../ex_038_007_XmlSerializer/Chien.cs | 33 +++ .../ex_038_007_XmlSerializer/Ménagerie.cs | 59 ++++ .../ex_038_007_XmlSerializer/Oiseau.cs | 33 +++ .../ex_038_007_XmlSerializer/Program.cs | 117 ++++++++ .../ex_038_007_XmlSerializer/XML/.gitignore | 4 + .../ex_038_007_XmlSerializer.csproj | 15 + .../ex_038_008_IXmlSerializable/Album.cs | 77 +++++ .../ex_038_008_IXmlSerializable/Artiste.cs | 80 +++++ .../ex_038_008_IXmlSerializable/Program.cs | 59 ++++ .../XML/.gitignore | 4 + .../ex_038_008_IXmlSerializable.csproj | 15 + .../ex_039_001_XDOM_bases/Program.cs | 62 ++++ .../ex_039_001_XDOM_bases/XML/volcans.xml | 90 ++++++ .../ex_039_001_XDOM_bases.csproj | 12 + .../ex_039_002_LINQ_to_XML/Program.cs | 116 ++++++++ .../ex_039_002_LINQ_to_XML/Volcan.cs | 108 +++++++ .../ex_039_002_LINQ_to_XML/XML/volcans.xml | 83 ++++++ .../ex_039_002_LINQ_to_XML.csproj | 12 + .../ex_040_001_LINQ_to_Json/Json/volcans.json | 100 +++++++ .../ex_040_001_LINQ_to_Json/Program.cs | 110 +++++++ .../ex_040_001_LINQ_to_Json/Volcan.cs | 108 +++++++ .../ex_040_001_LINQ_to_Json.csproj | 15 + .../ex_042_010_EF_CF_Many_to_Many/Album.cs | 67 +++++ .../AlbumArtiste.cs | 33 +++ .../AlbumArtisteDBEntities.cs | 55 ++++ .../ex_042_010_EF_CF_Many_to_Many/Artiste.cs | 76 +++++ .../DbContextInitializer.cs | 105 +++++++ .../ex_042_010_EF_CF_Many_to_Many/Program.cs | 84 ++++++ .../ex_042_010_EF_CF_Many_to_Many.csproj | 21 ++ .../Album.cs | 64 ++++ .../AlbumArtiste.cs | 33 +++ .../AlbumArtisteDBEntities.cs | 67 +++++ .../Artiste.cs | 73 +++++ .../DbContextInitializer.cs | 105 +++++++ .../Program.cs | 87 ++++++ ...42_011_EF_CF_Many_to_Many_FluentAPI.csproj | 15 + .../DbEntities/DbContextInitializer.cs | 94 ++++++ .../DbEntities/DictionaryItem.cs | 48 +++ .../DbEntities/LitEntity.cs | 79 +++++ .../DbEntities/NounoursDbEntities.cs | 82 ++++++ .../DbEntities/Score.cs | 29 ++ .../ex_042_012_EF_CF_Dictionary/Model/ILit.cs | 40 +++ .../Model/INounours.cs | 41 +++ .../Model/INounoursEqualityComparer.cs | 28 ++ .../ex_042_012_EF_CF_Dictionary/Model/Lit.cs | 66 +++++ .../Model/Nounours.cs | 96 ++++++ .../ex_042_012_EF_CF_Dictionary/Program.cs | 72 +++++ .../ex_042_012_EF_CF_Dictionary.csproj | 22 ++ .../DbEntities/AlbumArtiste.cs | 28 ++ .../DbEntities/AlbumArtisteDBEntities.cs | 78 +++++ .../DbEntities/AlbumEF.cs | 36 +++ .../DbEntities/ArtisteEF.cs | 33 +++ .../DbEntities/DbContextInitializer.cs | 135 +++++++++ .../Model/Album.cs | 51 ++++ .../Model/Artiste.cs | 61 ++++ .../Model/IAlbum.cs | 27 ++ .../Model/IArtiste.cs | 48 +++ .../Program.cs | 107 +++++++ ..._012_EF_CF_Many_to_Many_procurators.csproj | 21 ++ .../Program.cs | 41 +++ .../ex_042_013_EF_CF_TPT_Inheritance.csproj | 22 ++ .../Cercle.cs | 26 ++ .../DbContextInitializer.cs | 71 +++++ .../ex_042_014_EF_CF_TPH_Inheritance/Forme.cs | 37 +++ .../FormesDBEntities.cs | 65 +++++ .../Program.cs | 53 ++++ .../Rectangle.cs | 30 ++ .../ex_042_014_EF_CF_TPH_Inheritance.csproj | 22 ++ .../Program.cs | 42 +++ .../ex_042_015_EF_CF_TPC_Inheritance.csproj | 12 + .../DbContextInitializer.cs | 70 +++++ .../Nounours.cs | 103 +++++++ .../NounoursDBEntities.cs | 29 ++ .../Program.cs | 102 +++++++ ...16_EF_current_original_database_val.csproj | 22 ++ .../DbContextInitializer.cs | 70 +++++ .../Nounours.cs | 103 +++++++ .../NounoursDBEntities.cs | 29 ++ .../Program.cs | 129 ++++++++ ..._042_017_EF_concurrency_problematic.csproj | 22 ++ .../DbContextInitializer.cs | 70 +++++ .../Nounours.cs | 111 +++++++ .../NounoursDBEntities.cs | 41 +++ .../Program.cs | 157 ++++++++++ ...042_018_EF_concurrency_databaseWins.csproj | 22 ++ .../DbContextInitializer.cs | 70 +++++ .../Nounours.cs | 111 +++++++ .../NounoursDBEntities.cs | 41 +++ .../Program.cs | 184 ++++++++++++ ...x_042_019_EF_concurrency_clientWins.csproj | 22 ++ .../DbContextInitializer.cs | 70 +++++ .../Nounours.cs | 111 +++++++ .../NounoursDBEntities.cs | 41 +++ .../Program.cs | 233 +++++++++++++++ ...042_020_EF_concurrency_customDbProp.csproj | 22 ++ .../DbContextInitializer.cs | 70 +++++ .../Nounours.cs | 111 +++++++ .../NounoursDBEntities.cs | 41 +++ .../Program.cs | 244 ++++++++++++++++ ...42_021_EF_concurrency_customObjects.csproj | 22 ++ .../ex_050_001_CreatingAThread/Program.cs | 38 +++ .../ex_050_001_CreatingAThread.csproj | 12 + .../ex_050_002_attendre_un_thread/Program.cs | 81 +++++ .../ex_050_002_attendre_un_thread.csproj | 12 + .../Program.cs | 133 +++++++++ ...locales_et_partagées_entre_threads.csproj | 12 + .../Program.cs | 94 ++++++ .../ex_050_004_cadenas_et_sécurité.csproj | 12 + .../Program.cs | 71 +++++ .../ex_050_005_passage_de_paramètre.csproj | 12 + .../Program.cs | 45 +++ .../ex_050_006_gestion_des_exceptions.csproj | 12 + .../Program.cs | 69 +++++ .../arriere.txt | 169 +++++++++++ .../avant.txt | 200 +++++++++++++ ...ex_050_007_Foreground_vs_Background.csproj | 12 + .../ex_050_008_Priorité/Program.cs | 35 +++ .../ex_050_008_Priorité.csproj | 12 + .../ex_050_009_signalisation/Program.cs | 83 ++++++ ...050_009_notifications_entre_threads.csproj | 12 + .../ex_050_010_Threading_en_UWP/App.xaml | 7 + .../ex_050_010_Threading_en_UWP/App.xaml.cs | 100 +++++++ .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes .../Assets/StoreLogo.png | Bin 0 -> 1451 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes .../ex_050_010_Threading_en_UWP/MainPage.xaml | 31 ++ .../MainPage.xaml.cs | 113 +++++++ .../Package.appxmanifest | 49 ++++ .../Properties/AssemblyInfo.cs | 29 ++ .../Properties/Default.rd.xml | 31 ++ .../ex_050_010_Threading_en_UWP.csproj | 168 +++++++++++ .../ex_050_011_ThreadPool/Program.cs | 20 ++ .../ex_050_011_ThreadPool.csproj | 12 + .../Program.cs | 46 +++ .../ex_051_001_Démarrer_une_tâche.csproj | 12 + .../ex_051_002_valeur_de_retour/Program.cs | 34 +++ .../ex_051_002_valeur_de_retour.csproj | 12 + .../ex_051_003_gestion_exceptions/Program.cs | 40 +++ .../ex_051_003_gestion_exceptions.csproj | 12 + .../Program.cs | 78 +++++ .../ex_051_004_poursuite_continuations.csproj | 12 + .../Program.cs | 34 +++ .../ex_051_005_TaskCompletionSource.csproj | 12 + .../ex_051_006_TaskDelay/Program.cs | 23 ++ .../ex_051_006_TaskDelay.csproj | 12 + .../ex_052_001_problématique/Program.cs | 38 +++ .../ex_052_001_problématique.csproj | 12 + .../ex_052_002_problématique_2/Program.cs | 42 +++ .../ex_052_002_problématique_2.csproj | 12 + .../ex_052_003_problématique_3/Program.cs | 52 ++++ .../ex_052_003_problématique_3.csproj | 12 + .../ex_052_004_problématique_4/Program.cs | 67 +++++ .../ex_052_004_problématique_4.csproj | 12 + .../ex_052_005_problématique_5/Program.cs | 38 +++ .../ex_052_005_problématique_5.csproj | 12 + .../ex_052_006_problématique_6_UWP/App.xaml | 7 + .../App.xaml.cs | 100 +++++++ .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes .../Assets/StoreLogo.png | Bin 0 -> 1451 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes .../MainPage.xaml | 68 +++++ .../MainPage.xaml.cs | 125 ++++++++ .../Package.appxmanifest | 49 ++++ .../Properties/AssemblyInfo.cs | 29 ++ .../Properties/Default.rd.xml | 31 ++ .../ex_052_006_problématique_6_UWP.csproj | 167 +++++++++++ 588 files changed, 29850 insertions(+) create mode 100644 p02_Fondamentaux/ex_003_001_Main/Program.cs create mode 100644 p02_Fondamentaux/ex_003_001_Main/ex_003_001_Main.csproj create mode 100644 p02_Fondamentaux/ex_003_002_Main_HelloWorld/Program.cs create mode 100644 p02_Fondamentaux/ex_003_002_Main_HelloWorld/ex_003_002_Main_HelloWorld.csproj create mode 100644 p02_Fondamentaux/ex_003_003_Main_arguments/Program.cs create mode 100644 p02_Fondamentaux/ex_003_003_Main_arguments/Properties/launchSettings.json create mode 100644 p02_Fondamentaux/ex_003_003_Main_arguments/ReadMe.md create mode 100644 p02_Fondamentaux/ex_003_003_Main_arguments/ex_003_003_Main_arguments.csproj create mode 100644 p02_Fondamentaux/ex_003_004_Console/Program.cs create mode 100644 p02_Fondamentaux/ex_003_004_Console/ex_003_004_Console.csproj create mode 100644 p02_Fondamentaux/ex_004_001_TypesNumeriques/Program.cs create mode 100644 p02_Fondamentaux/ex_004_001_TypesNumeriques/ex_004_001_TypesNumeriques.csproj create mode 100644 p02_Fondamentaux/ex_004_002_Math/Program.cs create mode 100644 p02_Fondamentaux/ex_004_002_Math/ex_004_002_Math.csproj create mode 100644 p02_Fondamentaux/ex_004_003_Random/Program.cs create mode 100644 p02_Fondamentaux/ex_004_003_Random/ex_004_003_Random.csproj create mode 100644 p02_Fondamentaux/ex_004_004_TypeBool/Program.cs create mode 100644 p02_Fondamentaux/ex_004_004_TypeBool/ex_004_004_TypeBool.csproj create mode 100644 p02_Fondamentaux/ex_004_005_TypeChar/Program.cs create mode 100644 p02_Fondamentaux/ex_004_005_TypeChar/ex_004_005_TypeChar.csproj create mode 100644 p02_Fondamentaux/ex_004_006_TimeSpan_et_DateTime/Program.cs create mode 100644 p02_Fondamentaux/ex_004_006_TimeSpan_et_DateTime/ex_004_006_TimeSpan_et_DateTime.csproj create mode 100644 p02_Fondamentaux/ex_004_007_DureeDeVie/Program.cs create mode 100644 p02_Fondamentaux/ex_004_007_DureeDeVie/ex_004_007_DureeDeVie.csproj create mode 100644 p02_Fondamentaux/ex_004_008_var/Program.cs create mode 100644 p02_Fondamentaux/ex_004_008_var/ex_004_008_var.csproj create mode 100644 p02_Fondamentaux/ex_004_009_Tuple/Program.CSharp7.cs create mode 100644 p02_Fondamentaux/ex_004_009_Tuple/Program.cs create mode 100644 p02_Fondamentaux/ex_004_009_Tuple/ex_004_009_Tuple.csproj create mode 100644 p02_Fondamentaux/ex_004_010_GuidStruct/Program.cs create mode 100644 p02_Fondamentaux/ex_004_010_GuidStruct/ex_004_010_GuidStruct.csproj create mode 100644 p02_Fondamentaux/ex_005_001_tableaux/Program.cs create mode 100644 p02_Fondamentaux/ex_005_001_tableaux/ex_005_001_tableaux.csproj create mode 100644 p02_Fondamentaux/ex_005_002_copie_de_tableaux/Program.cs create mode 100644 p02_Fondamentaux/ex_005_002_copie_de_tableaux/ex_005_002_copie_de_tableaux.csproj create mode 100644 p02_Fondamentaux/ex_005_003_tableaux_multiDimensions/Program.cs create mode 100644 p02_Fondamentaux/ex_005_003_tableaux_multiDimensions/ex_005_003_tableaux_multiDimensions.csproj create mode 100644 p02_Fondamentaux/ex_006_001_string/Program.cs create mode 100644 p02_Fondamentaux/ex_006_001_string/ex_006_001_string.csproj create mode 100644 p02_Fondamentaux/ex_006_002_StringBuilder/Program.cs create mode 100644 p02_Fondamentaux/ex_006_002_StringBuilder/ex_006_002_StringBuilder.csproj create mode 100644 p02_Fondamentaux/ex_007_001_enum/Program.cs create mode 100644 p02_Fondamentaux/ex_007_001_enum/ex_007_001_enum.csproj create mode 100644 p02_Fondamentaux/ex_008_001_if_else/Program.cs create mode 100644 p02_Fondamentaux/ex_008_001_if_else/ex_008_001_if_else.csproj create mode 100644 p02_Fondamentaux/ex_008_002_switch/Program.cs create mode 100644 p02_Fondamentaux/ex_008_002_switch/ex_008_002_switch.csproj create mode 100644 p02_Fondamentaux/ex_008_003_ternary_operator/Program.cs create mode 100644 p02_Fondamentaux/ex_008_003_ternary_operator/ex_008_003_ternary_operator.csproj create mode 100644 p02_Fondamentaux/ex_008_004_null_operators/Program.cs create mode 100644 p02_Fondamentaux/ex_008_004_null_operators/ex_008_004_null_operators.csproj create mode 100644 p02_Fondamentaux/ex_008_005_pattern_matching/Program.cs create mode 100644 p02_Fondamentaux/ex_008_005_pattern_matching/ex_008_005_pattern_matching.csproj create mode 100644 p02_Fondamentaux/ex_009_001_bouclesIteratives/Program.cs create mode 100644 p02_Fondamentaux/ex_009_001_bouclesIteratives/ex_009_001_bouclesIteratives.csproj create mode 100644 p02_Fondamentaux/ex_010_001_methodParametersAndModifiers/Program.cs create mode 100644 p02_Fondamentaux/ex_010_001_methodParametersAndModifiers/ex_010_001_methodParametersAndModifiers.csproj create mode 100644 p02_Fondamentaux/ex_010_002_optionalParameters/Program.cs create mode 100644 p02_Fondamentaux/ex_010_002_optionalParameters/ex_010_002_optionalParameters.csproj create mode 100644 p02_Fondamentaux/ex_010_003_interets_des_optionalparameters/Program.cs create mode 100644 p02_Fondamentaux/ex_010_003_interets_des_optionalparameters/ex_010_003_interets_des_optionalparameters.csproj create mode 100644 p02_Fondamentaux/ex_012_001_nullableTypes/Program.cs create mode 100644 p02_Fondamentaux/ex_012_001_nullableTypes/ex_012_001_nullableTypes.csproj create mode 100644 p02_Fondamentaux/ex_013_001_FormattingParsingNumEtBool/Program.cs create mode 100644 p02_Fondamentaux/ex_013_001_FormattingParsingNumEtBool/ex_013_001_FormattingParsingNumEtBool.csproj create mode 100644 p02_Fondamentaux/ex_013_002_FormattingParsingDateTime/Program.cs create mode 100644 p02_Fondamentaux/ex_013_002_FormattingParsingDateTime/ex_013_002_FormattingParsingDateTime.csproj create mode 100644 p03_POO/ex_014_001_namespace_et_nomDUneClasse/Program.cs create mode 100644 p03_POO/ex_014_001_namespace_et_nomDUneClasse/ex_014_001_namespace_et_nomDUneClasse.csproj create mode 100644 p03_POO/ex_014_002_typesImbriques/Program.cs create mode 100644 p03_POO/ex_014_002_typesImbriques/ex_014_002_typesImbriques.csproj create mode 100644 p03_POO/ex_014_003_ClasseChampInitialiseurs/Program.cs create mode 100644 p03_POO/ex_014_003_ClasseChampInitialiseurs/ex_014_003_ClasseChampInitialiseurs.csproj create mode 100644 p03_POO/ex_014_004_constructeurs/Program.cs create mode 100644 p03_POO/ex_014_004_constructeurs/ex_014_004_constructeurs.csproj create mode 100644 p03_POO/ex_014_005_methodes/Program.cs create mode 100644 p03_POO/ex_014_005_methodes/ex_014_005_methodes.csproj create mode 100644 p03_POO/ex_014_006_object_ToString/Program.cs create mode 100644 p03_POO/ex_014_006_object_ToString/ex_014_006_object_ToString.csproj create mode 100644 p03_POO/ex_014_007_expression_bodied_methods/Program.cs create mode 100644 p03_POO/ex_014_007_expression_bodied_methods/ex_014_007_expression_bodied_methods.csproj create mode 100644 p03_POO/ex_014_008_deconstruction/Program.cs create mode 100644 p03_POO/ex_014_008_deconstruction/ex_014_008_deconstruction.csproj create mode 100644 p03_POO/ex_015_001_static/Program.cs create mode 100644 p03_POO/ex_015_001_static/ex_015_001_static.csproj create mode 100644 p03_POO/ex_015_002_ordreAppelStatic/Program.cs create mode 100644 p03_POO/ex_015_002_ordreAppelStatic/ex_015_002_ordreAppelStatic.csproj create mode 100644 p03_POO/ex_015_003_singleton/Program.cs create mode 100644 p03_POO/ex_015_003_singleton/ex_015_003_singleton.csproj create mode 100644 p03_POO/ex_015_004_using_static/Program.cs create mode 100644 p03_POO/ex_015_004_using_static/ex_015_004_using_static.csproj create mode 100644 p03_POO/ex_016_001_getters_setters_methods/Program.cs create mode 100644 p03_POO/ex_016_001_getters_setters_methods/ex_016_001_getters_setters_methods.csproj create mode 100644 p03_POO/ex_016_002_properties/Program.cs create mode 100644 p03_POO/ex_016_002_properties/ex_016_002_properties.csproj create mode 100644 p03_POO/ex_016_003_indexers/Program.cs create mode 100644 p03_POO/ex_016_003_indexers/ex_016_003_indexers.csproj create mode 100644 p03_POO/ex_016_004_readonly/Program.cs create mode 100644 p03_POO/ex_016_004_readonly/ex_016_004_readonly.csproj create mode 100644 p03_POO/ex_016_005_partial/MaClasse.QqsDétails.cs create mode 100644 p03_POO/ex_016_005_partial/MaClasse.cs create mode 100644 p03_POO/ex_016_005_partial/Program.cs create mode 100644 p03_POO/ex_016_005_partial/ex_016_005_partial.csproj create mode 100644 p03_POO/ex_016_006_local_functions/Program.cs create mode 100644 p03_POO/ex_016_006_local_functions/ex_016_006_local_functions.csproj create mode 100644 p03_POO/ex_017_001_heritage_syntaxe/Program.cs create mode 100644 p03_POO/ex_017_001_heritage_syntaxe/ex_017_001_heritage_syntaxe.csproj create mode 100644 p03_POO/ex_017_002_redefinitionDeMethodes/Program.cs create mode 100644 p03_POO/ex_017_002_redefinitionDeMethodes/ex_017_002_redefinitionDeMethodes.csproj create mode 100644 p03_POO/ex_017_003_initialiseurs_constructeurs/Program.cs create mode 100644 p03_POO/ex_017_003_initialiseurs_constructeurs/ex_017_003_initialiseurs_constructeurs.csproj create mode 100644 p03_POO/ex_017_004_casting/Program.cs create mode 100644 p03_POO/ex_017_004_casting/ex_017_004_casting.csproj create mode 100644 p03_POO/ex_018_001_polymorphisme/Program.cs create mode 100644 p03_POO/ex_018_001_polymorphisme/ex_018_001_polymorphisme.csproj create mode 100644 p03_POO/ex_018_002_abstract/Program.cs create mode 100644 p03_POO/ex_018_002_abstract/ex_018_002_abstract.csproj create mode 100644 p03_POO/ex_019_001_interfaces/Program.cs create mode 100644 p03_POO/ex_019_001_interfaces/ex_019_001_interfaces.csproj create mode 100644 p03_POO/ex_020_001_structures/Program.cs create mode 100644 p03_POO/ex_020_001_structures/ex_020_001_structures.csproj create mode 100644 p03_POO/ex_021_001_patternComposite/Program.cs create mode 100644 p03_POO/ex_021_001_patternComposite/ex_021_001_patternComposite.csproj create mode 100644 p03_POO/ex_021_002_patternStrategy/Program.cs create mode 100644 p03_POO/ex_021_002_patternStrategy/ex_021_002_patternStrategy.csproj create mode 100644 p04_AdvancedCSharp/ex_022_001_Generics_def_du_pb/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_001_Generics_def_du_pb/ex_022_001_Generics_def_du_pb.csproj create mode 100644 p04_AdvancedCSharp/ex_022_002_Generics_EtPourquoiPasObject/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_002_Generics_EtPourquoiPasObject/ex_022_002_Generics_EtPourquoiPasObject.csproj create mode 100644 p04_AdvancedCSharp/ex_022_003_Generics_syntaxe/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_003_Generics_syntaxe/ex_022_003_Generics_syntaxe.csproj create mode 100644 p04_AdvancedCSharp/ex_022_004_Generics_default/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_004_Generics_default/ex_022_004_Generics_default.csproj create mode 100644 p04_AdvancedCSharp/ex_022_005_Generics_constraints/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_005_Generics_constraints/ex_022_005_Generics_constraints.csproj create mode 100644 p04_AdvancedCSharp/ex_022_006_Generics_constraints2/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_006_Generics_constraints2/ex_022_006_Generics_constraints2.csproj create mode 100644 p04_AdvancedCSharp/ex_022_007_Generics_subclassing/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_007_Generics_subclassing/ex_022_007_Generics_subclassing.csproj create mode 100644 p04_AdvancedCSharp/ex_022_008_CovarianceClasses/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_008_CovarianceClasses/ex_022_008_CovarianceClasses.csproj create mode 100644 p04_AdvancedCSharp/ex_022_009_CovarianceInterfaces/Program.cs create mode 100644 p04_AdvancedCSharp/ex_022_009_CovarianceInterfaces/ex_022_009_CovarianceInterfaces.csproj create mode 100644 p04_AdvancedCSharp/ex_023_001_IEnumerator_ex1/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_001_IEnumerator_ex1/ex_023_001_IEnumerator_ex1.csproj create mode 100644 p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/StrangeCollection.cs create mode 100644 p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/ex_023_002_IEnumerator_ex2.csproj create mode 100644 p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/StrangeCollection.cs create mode 100644 p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/ex_023_003_IEnumerator_ex3.csproj create mode 100644 p04_AdvancedCSharp/ex_023_004_ArrayClass/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_004_ArrayClass/ex_023_004_ArrayClass.csproj create mode 100644 p04_AdvancedCSharp/ex_023_005_Queue/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_005_Queue/ex_023_005_Queue.csproj create mode 100644 p04_AdvancedCSharp/ex_023_006_Stack/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_006_Stack/ex_023_006_Stack.csproj create mode 100644 p04_AdvancedCSharp/ex_023_007_LinkedList/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_007_LinkedList/ex_023_007_LinkedList.csproj create mode 100644 p04_AdvancedCSharp/ex_023_008_List/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_008_List/ex_023_008_List.csproj create mode 100644 p04_AdvancedCSharp/ex_023_009_HashSet_and_SortedSet/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_009_HashSet_and_SortedSet/ex_023_009_HashSet_and_SortedSet.csproj create mode 100644 p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/VieuxNounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/ex_023_010_EqualityProtocoleOnReferences.csproj create mode 100644 p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/VieuxNounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/ex_023_011_EqualityProtocoleOnValues.csproj create mode 100644 p04_AdvancedCSharp/ex_023_012_EqualityComparer/Nounours.EqualityComparer.cs create mode 100644 p04_AdvancedCSharp/ex_023_012_EqualityComparer/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_012_EqualityComparer/NounoursNbPoilsEqualityComparer.cs create mode 100644 p04_AdvancedCSharp/ex_023_012_EqualityComparer/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_012_EqualityComparer/ex_023_012_EqualityComparer.csproj create mode 100644 p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Nounours.NbPoilsComparer.cs create mode 100644 p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/NounoursDateComparer.cs create mode 100644 p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/ex_023_013_OrderComparisonProtocole.csproj create mode 100644 p04_AdvancedCSharp/ex_023_014_Dictionary/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_014_Dictionary/ex_023_014_Dictionary.csproj create mode 100644 p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/NounoursNbPoilsEqualityComparer.cs create mode 100644 p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/VieuxNounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/ex_023_015_DictionaryCustomType.csproj create mode 100644 p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/MonLit.cs create mode 100644 p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/MonLit2.cs create mode 100644 p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Nounours2.cs create mode 100644 p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/ex_023_016_ReadOnlyCollection.csproj create mode 100644 p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/INounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/MonLit.cs create mode 100644 p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/ex_023_017_Deep_Read_only_collections_dll.csproj create mode 100644 p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_exe/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_exe/ex_023_017_Deep_Read_only_collections_exe.csproj create mode 100644 p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/MonLit.cs create mode 100644 p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/ex_023_018_ReadOnlyDictionaries.csproj create mode 100644 p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/INounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/MonLit.cs create mode 100644 p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/Nounours.cs create mode 100644 p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/ex_023_019_ReadOnlyDictionary_and_values_dll.csproj create mode 100644 p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_exe/Program.cs create mode 100644 p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_exe/ex_023_019_ReadOnlyDictionary_and_values_exe.csproj create mode 100644 p05_More_dotNet/ex_024_001_exceptions_Contexte/Program.cs create mode 100644 p05_More_dotNet/ex_024_001_exceptions_Contexte/ex_024_001_exceptions_Contexte.csproj create mode 100644 p05_More_dotNet/ex_024_002_parse/Program.cs create mode 100644 p05_More_dotNet/ex_024_002_parse/ex_024_002_parse.csproj create mode 100644 p05_More_dotNet/ex_024_003_exceptions/Program.cs create mode 100644 p05_More_dotNet/ex_024_003_exceptions/ex_024_003_exceptions.csproj create mode 100644 p05_More_dotNet/ex_024_004_propagation_exceptions/Program.cs create mode 100644 p05_More_dotNet/ex_024_004_propagation_exceptions/ex_024_004_propagation_exceptions.csproj create mode 100644 p05_More_dotNet/ex_024_005_exceptions_personnalisees/Program.cs create mode 100644 p05_More_dotNet/ex_024_005_exceptions_personnalisees/ex_024_005_exceptions_personnalisees.csproj create mode 100644 p05_More_dotNet/ex_025_001_DebugTrace/Program.cs create mode 100644 p05_More_dotNet/ex_025_001_DebugTrace/ex_025_001_DebugTrace.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Carré.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Cube.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Droite.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/IModifieur.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/ex_028_001_intro_avec_interfaces.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/Droite.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/MaClasseDeMaths.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/ex_028_002_intro_avec_delegate.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Carré.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Cube.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Droite.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/IModifieur.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/ex_028_003_interface_as_parameter.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/Droite.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/MaClasseDeMaths.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/ex_028_004_delegate_as_parameter.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/Droite.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/MaClasseDeMaths.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/ex_028_005_nested_delegate.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Carré.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Cube.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Droite.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/IModifieur.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/ex_028_006_Strategy_et_interface.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/Droite.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/MaClasseDeMaths.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/ex_028_007_delegate_versus_Strategy.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/AffichePourcentage.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ClasseQuiFaitDuGrosTravail.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ClearProgression.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/IProgression.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ProgressBar.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ex_028_008_multicast_et_interfaces.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/GrosTravail.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/ex_028_009_multicast_delegate.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/GrosTravail.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/ex_028_010_multicast_delegate_return_value.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/Broadcaster.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ConcreteSubscriber.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ISubscriber.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/InfoSportBroadcaster.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ex_028_011_Broadcaster_Subscriber.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Broadcaster.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Subscriber.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/ex_028_012_delegate_Broadcaster_Subscriber.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_013_Predicate/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_013_Predicate/ex_028_013_Predicate.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_014_Func/Droite.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_014_Func/MaClasseDeMaths.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_014_Func/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_014_Func/ex_028_014_Func.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_028_015_Action/GrosTravail.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_015_Action/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_028_015_Action/ex_028_015_Action.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Broadcaster.cs create mode 100644 p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Subscriber.cs create mode 100644 p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/ex_029_001_event_Broadcaster_Subscriber.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Broadcaster.cs create mode 100644 p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/InfoChangedEventArgs.cs create mode 100644 p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Subscriber.cs create mode 100644 p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/ex_029_002_event_standard_pattern.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_030_001_anonymousMethods/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_030_001_anonymousMethods/ex_030_001_anonymousMethods.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_030_002_lambdaExpressions/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_030_002_lambdaExpressions/ex_030_002_lambdaExpressions.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/GrosTravail.cs create mode 100644 p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/ex_030_003_lambdaExpressions.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/ex_031_001_decouverteDeLINQ.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_002_extensionMethods/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_002_extensionMethods/ex_031_002_extensionMethods.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_003_anonymousTypes/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_003_anonymousTypes/ex_031_003_anonymousTypes.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_004_LINQ_intro/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_004_LINQ_intro/ex_031_004_LINQ_intro.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/ex_031_005_LINQ_deferredExecution.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_005_LINQ_operators/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/ex_031_006_LINQ_filtering.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/NounoursDateComparer.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/ex_031_007_LINQ_ordering.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/ex_031_008_LINQ_projecting.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/ex_031_009_LINQ_element_operators.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/ex_031_010_LINQ_aggregation_methods.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/ex_031_011_LINQ_grouping.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Enfant.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/ex_031_012_LINQ_joining.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_013_LINQ_set_operators/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_013_LINQ_set_operators/ex_031_013_LINQ_set_operators.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_014_LINQ_quantifiers/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_014_LINQ_quantifiers/ex_031_014_LINQ_quantifiers.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_015_LINQ_generation_methods/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_015_LINQ_generation_methods/ex_031_015_LINQ_generation_methods.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/Nounours.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/ex_031_016_LINQ_conversion_methods.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/README.md create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/Applications/Program.cs create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/Applications/ex_036_001_Reflection.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chat.cs create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chien.cs create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Oiseau.cs create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/ex_036_001_ChatChienOiseau.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/MammifereDll/Mammifere.cs create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/MammifereDll/ex_036_001_Mammifere.csproj create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_ChatChienOiseau.deps.json create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_ChatChienOiseau.dll create mode 100644 p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_Mammifere.dll create mode 100644 p07_Persistance/ex_037_001_File_and_Directory_management/Program.cs create mode 100644 p07_Persistance/ex_037_001_File_and_Directory_management/ex_037_001_File_and_Directory_management.csproj create mode 100644 p07_Persistance/ex_037_002_FileStream/Program.cs create mode 100644 p07_Persistance/ex_037_002_FileStream/ex_037_002_FileStream.csproj create mode 100644 p07_Persistance/ex_037_002_FileStream/exemple_filestream.txt create mode 100644 p07_Persistance/ex_037_002_FileStream/fichier.txt create mode 100644 p07_Persistance/ex_037_003_TextReader_TextWriter/Program.cs create mode 100644 p07_Persistance/ex_037_003_TextReader_TextWriter/ex_037_003_TextReader_TextWriter.csproj create mode 100644 p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/Nounours.cs create mode 100644 p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/Program.cs create mode 100644 p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/ex_037_004_BinaryReader_BinaryWriter.csproj create mode 100644 p07_Persistance/ex_037_005_XmlReader_XmlWriter/Nounours.cs create mode 100644 p07_Persistance/ex_037_005_XmlReader_XmlWriter/Program.cs create mode 100644 p07_Persistance/ex_037_005_XmlReader_XmlWriter/XML/nounours.xml create mode 100644 p07_Persistance/ex_037_005_XmlReader_XmlWriter/ex_037_005_XmlReader_XmlWriter.csproj create mode 100644 p07_Persistance/ex_038_001_DataContractSerializer_bases/Nounours.cs create mode 100644 p07_Persistance/ex_038_001_DataContractSerializer_bases/Program.cs create mode 100644 p07_Persistance/ex_038_001_DataContractSerializer_bases/XML/.gitignore create mode 100644 p07_Persistance/ex_038_001_DataContractSerializer_bases/ex_038_001_DataContractSerializer_bases.csproj create mode 100644 p07_Persistance/ex_038_002_DataContract_subclassing/Animal.cs create mode 100644 p07_Persistance/ex_038_002_DataContract_subclassing/Chat.cs create mode 100644 p07_Persistance/ex_038_002_DataContract_subclassing/Chien.cs create mode 100644 p07_Persistance/ex_038_002_DataContract_subclassing/Oiseau.cs create mode 100644 p07_Persistance/ex_038_002_DataContract_subclassing/Program.cs create mode 100644 p07_Persistance/ex_038_002_DataContract_subclassing/XML/.gitignore create mode 100644 p07_Persistance/ex_038_002_DataContract_subclassing/ex_038_002_DataContract_subclassing.csproj create mode 100644 p07_Persistance/ex_038_003_DataContract_ObjectReferences/Album.cs create mode 100644 p07_Persistance/ex_038_003_DataContract_ObjectReferences/Artiste.cs create mode 100644 p07_Persistance/ex_038_003_DataContract_ObjectReferences/Morceau.cs create mode 100644 p07_Persistance/ex_038_003_DataContract_ObjectReferences/Program.cs create mode 100644 p07_Persistance/ex_038_003_DataContract_ObjectReferences/XML/.gitignore create mode 100644 p07_Persistance/ex_038_003_DataContract_ObjectReferences/ex_038_003_DataContract_ObjectReferences.csproj create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/Animal.cs create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/AnimalList.cs create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/Chat.cs create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/Chien.cs create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/Ménagerie.cs create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/Oiseau.cs create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/Program.cs create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/XML/.gitignore create mode 100644 p07_Persistance/ex_038_004_DataContract_Collections/ex_038_004_DataContract_Collections.csproj create mode 100644 p07_Persistance/ex_038_005_DataContract_Hooks/Animal.cs create mode 100644 p07_Persistance/ex_038_005_DataContract_Hooks/Animal2.cs create mode 100644 p07_Persistance/ex_038_005_DataContract_Hooks/Program.cs create mode 100644 p07_Persistance/ex_038_005_DataContract_Hooks/XML/.gitignore create mode 100644 p07_Persistance/ex_038_005_DataContract_Hooks/ex_038_005_DataContract_Hooks.csproj create mode 100644 p07_Persistance/ex_038_006_Binary_Serializable/Nounours.cs create mode 100644 p07_Persistance/ex_038_006_Binary_Serializable/Program.cs create mode 100644 p07_Persistance/ex_038_006_Binary_Serializable/ex_038_006_Binary_Serializable.csproj create mode 100644 p07_Persistance/ex_038_006_Binary_Serializable/result/.gitignore create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/Animal.cs create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/AnimalList.cs create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/Chat.cs create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/Chien.cs create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/Ménagerie.cs create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/Oiseau.cs create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/Program.cs create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/XML/.gitignore create mode 100644 p07_Persistance/ex_038_007_XmlSerializer/ex_038_007_XmlSerializer.csproj create mode 100644 p07_Persistance/ex_038_008_IXmlSerializable/Album.cs create mode 100644 p07_Persistance/ex_038_008_IXmlSerializable/Artiste.cs create mode 100644 p07_Persistance/ex_038_008_IXmlSerializable/Program.cs create mode 100644 p07_Persistance/ex_038_008_IXmlSerializable/XML/.gitignore create mode 100644 p07_Persistance/ex_038_008_IXmlSerializable/ex_038_008_IXmlSerializable.csproj create mode 100644 p07_Persistance/ex_039_001_XDOM_bases/Program.cs create mode 100644 p07_Persistance/ex_039_001_XDOM_bases/XML/volcans.xml create mode 100644 p07_Persistance/ex_039_001_XDOM_bases/ex_039_001_XDOM_bases.csproj create mode 100644 p07_Persistance/ex_039_002_LINQ_to_XML/Program.cs create mode 100644 p07_Persistance/ex_039_002_LINQ_to_XML/Volcan.cs create mode 100644 p07_Persistance/ex_039_002_LINQ_to_XML/XML/volcans.xml create mode 100644 p07_Persistance/ex_039_002_LINQ_to_XML/ex_039_002_LINQ_to_XML.csproj create mode 100644 p07_Persistance/ex_040_001_LINQ_to_Json/Json/volcans.json create mode 100644 p07_Persistance/ex_040_001_LINQ_to_Json/Program.cs create mode 100644 p07_Persistance/ex_040_001_LINQ_to_Json/Volcan.cs create mode 100644 p07_Persistance/ex_040_001_LINQ_to_Json/ex_040_001_LINQ_to_Json.csproj create mode 100644 p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Album.cs create mode 100644 p07_Persistance/ex_042_010_EF_CF_Many_to_Many/AlbumArtiste.cs create mode 100644 p07_Persistance/ex_042_010_EF_CF_Many_to_Many/AlbumArtisteDBEntities.cs create mode 100644 p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Artiste.cs create mode 100644 p07_Persistance/ex_042_010_EF_CF_Many_to_Many/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Program.cs create mode 100644 p07_Persistance/ex_042_010_EF_CF_Many_to_Many/ex_042_010_EF_CF_Many_to_Many.csproj create mode 100644 p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Album.cs create mode 100644 p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/AlbumArtiste.cs create mode 100644 p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/AlbumArtisteDBEntities.cs create mode 100644 p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Artiste.cs create mode 100644 p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Program.cs create mode 100644 p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/ex_042_011_EF_CF_Many_to_Many_FluentAPI.csproj create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/DictionaryItem.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/LitEntity.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/NounoursDbEntities.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/Score.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/ILit.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/INounours.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/INounoursEqualityComparer.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/Lit.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/Nounours.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/Program.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Dictionary/ex_042_012_EF_CF_Dictionary.csproj create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumArtiste.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumArtisteDBEntities.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumEF.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/ArtisteEF.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/Album.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/Artiste.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/IAlbum.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/IArtiste.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Program.cs create mode 100644 p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/ex_042_012_EF_CF_Many_to_Many_procurators.csproj create mode 100644 p07_Persistance/ex_042_013_EF_CF_TPT_Inheritance/Program.cs create mode 100644 p07_Persistance/ex_042_013_EF_CF_TPT_Inheritance/ex_042_013_EF_CF_TPT_Inheritance.csproj create mode 100644 p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Cercle.cs create mode 100644 p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Forme.cs create mode 100644 p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/FormesDBEntities.cs create mode 100644 p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Program.cs create mode 100644 p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Rectangle.cs create mode 100644 p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/ex_042_014_EF_CF_TPH_Inheritance.csproj create mode 100644 p07_Persistance/ex_042_015_EF_CF_TPC_Inheritance/Program.cs create mode 100644 p07_Persistance/ex_042_015_EF_CF_TPC_Inheritance/ex_042_015_EF_CF_TPC_Inheritance.csproj create mode 100644 p07_Persistance/ex_042_016_EF_current_original_database_val/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_016_EF_current_original_database_val/Nounours.cs create mode 100644 p07_Persistance/ex_042_016_EF_current_original_database_val/NounoursDBEntities.cs create mode 100644 p07_Persistance/ex_042_016_EF_current_original_database_val/Program.cs create mode 100644 p07_Persistance/ex_042_016_EF_current_original_database_val/ex_042_016_EF_current_original_database_val.csproj create mode 100644 p07_Persistance/ex_042_017_EF_concurrency_problematic/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_017_EF_concurrency_problematic/Nounours.cs create mode 100644 p07_Persistance/ex_042_017_EF_concurrency_problematic/NounoursDBEntities.cs create mode 100644 p07_Persistance/ex_042_017_EF_concurrency_problematic/Program.cs create mode 100644 p07_Persistance/ex_042_017_EF_concurrency_problematic/ex_042_017_EF_concurrency_problematic.csproj create mode 100644 p07_Persistance/ex_042_018_EF_concurrency_databaseWins/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_018_EF_concurrency_databaseWins/Nounours.cs create mode 100644 p07_Persistance/ex_042_018_EF_concurrency_databaseWins/NounoursDBEntities.cs create mode 100644 p07_Persistance/ex_042_018_EF_concurrency_databaseWins/Program.cs create mode 100644 p07_Persistance/ex_042_018_EF_concurrency_databaseWins/ex_042_018_EF_concurrency_databaseWins.csproj create mode 100644 p07_Persistance/ex_042_019_EF_concurrency_clientWins/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_019_EF_concurrency_clientWins/Nounours.cs create mode 100644 p07_Persistance/ex_042_019_EF_concurrency_clientWins/NounoursDBEntities.cs create mode 100644 p07_Persistance/ex_042_019_EF_concurrency_clientWins/Program.cs create mode 100644 p07_Persistance/ex_042_019_EF_concurrency_clientWins/ex_042_019_EF_concurrency_clientWins.csproj create mode 100644 p07_Persistance/ex_042_020_EF_concurrency_customDbProp/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_020_EF_concurrency_customDbProp/Nounours.cs create mode 100644 p07_Persistance/ex_042_020_EF_concurrency_customDbProp/NounoursDBEntities.cs create mode 100644 p07_Persistance/ex_042_020_EF_concurrency_customDbProp/Program.cs create mode 100644 p07_Persistance/ex_042_020_EF_concurrency_customDbProp/ex_042_020_EF_concurrency_customDbProp.csproj create mode 100644 p07_Persistance/ex_042_021_EF_concurrency_customObjects/DbContextInitializer.cs create mode 100644 p07_Persistance/ex_042_021_EF_concurrency_customObjects/Nounours.cs create mode 100644 p07_Persistance/ex_042_021_EF_concurrency_customObjects/NounoursDBEntities.cs create mode 100644 p07_Persistance/ex_042_021_EF_concurrency_customObjects/Program.cs create mode 100644 p07_Persistance/ex_042_021_EF_concurrency_customObjects/ex_042_021_EF_concurrency_customObjects.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_001_CreatingAThread/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_001_CreatingAThread/ex_050_001_CreatingAThread.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_002_attendre_un_thread/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_002_attendre_un_thread/ex_050_002_attendre_un_thread.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_003_Variables_locales_et_partagées_entre_threads/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_003_Variables_locales_et_partagées_entre_threads/ex_050_003_Variables_locales_et_partagées_entre_threads.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_004_cadenas_et_sécurité/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_004_cadenas_et_sécurité/ex_050_004_cadenas_et_sécurité.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_005_passage_de_paramètre/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_005_passage_de_paramètre/ex_050_005_passage_de_paramètre.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_006_gestion_des_exceptions/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_006_gestion_des_exceptions/ex_050_006_gestion_des_exceptions.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/arriere.txt create mode 100644 p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/avant.txt create mode 100644 p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/ex_050_007_Foreground_vs_Background.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_008_Priorité/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_008_Priorité/ex_050_008_Priorité.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_009_signalisation/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_009_signalisation/ex_050_009_notifications_entre_threads.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/App.xaml create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/App.xaml.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/LockScreenLogo.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/SplashScreen.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square150x150Logo.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square44x44Logo.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/StoreLogo.png create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Wide310x150Logo.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/MainPage.xaml create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/MainPage.xaml.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Package.appxmanifest create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Properties/AssemblyInfo.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Properties/Default.rd.xml create mode 100644 p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/ex_050_010_Threading_en_UWP.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_050_011_ThreadPool/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_050_011_ThreadPool/ex_050_011_ThreadPool.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_051_001_Démarrer_une_tâche/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_051_001_Démarrer_une_tâche/ex_051_001_Démarrer_une_tâche.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_051_002_valeur_de_retour/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_051_002_valeur_de_retour/ex_051_002_valeur_de_retour.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_051_003_gestion_exceptions/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_051_003_gestion_exceptions/ex_051_003_gestion_exceptions.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_051_004_poursuite_continuations/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_051_004_poursuite_continuations/ex_051_004_poursuite_continuations.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_051_005_TaskCompletionSource/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_051_005_TaskCompletionSource/ex_051_005_TaskCompletionSource.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_051_006_TaskDelay/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_051_006_TaskDelay/ex_051_006_TaskDelay.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_052_001_problématique/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_052_001_problématique/ex_052_001_problématique.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_052_002_problématique_2/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_052_002_problématique_2/ex_052_002_problématique_2.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_052_003_problématique_3/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_052_003_problématique_3/ex_052_003_problématique_3.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_052_004_problématique_4/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_052_004_problématique_4/ex_052_004_problématique_4.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_052_005_problématique_5/Program.cs create mode 100644 p09_Concurrency_Asynchrony/ex_052_005_problématique_5/ex_052_005_problématique_5.csproj create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/App.xaml create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/App.xaml.cs create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Assets/LockScreenLogo.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Assets/SplashScreen.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Assets/Square150x150Logo.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Assets/Square44x44Logo.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Assets/StoreLogo.png create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Assets/Wide310x150Logo.scale-200.png create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/MainPage.xaml create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/MainPage.xaml.cs create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Package.appxmanifest create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Properties/AssemblyInfo.cs create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/Properties/Default.rd.xml create mode 100644 p09_Concurrency_Asynchrony/ex_052_006_problématique_6_UWP/ex_052_006_problématique_6_UWP.csproj diff --git a/p02_Fondamentaux/ex_003_001_Main/Program.cs b/p02_Fondamentaux/ex_003_001_Main/Program.cs new file mode 100644 index 0000000..330f935 --- /dev/null +++ b/p02_Fondamentaux/ex_003_001_Main/Program.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-21 +// +// ======================================================================== + +// le point d'entrée d'une application Console est la fonction Main (statique) d'une classe quelconque +// que Visual Studio nomme par défaut Program, et qu'il place automatiquement dans l'espace de noms +// portant le même nom que le projet. Vous pouvez changer le nom de la classe et l'espace de noms. +namespace ex_003_001_Main +{ + class Program + { + /// + /// En C#, tous les objets dérivent de la classe object, et tout est objet. + /// En conséquence, la fonction Main doit être dans une classe (ici la classe Program). + /// La fonction Main est le point d'entrée du programme. Elle est statique pour pouvoir + /// être appelée sans que Program soit instancié. Ce n'est pas important si ceci n'est pas + /// encore clair pour vous, à ce moment-là du cours. + /// + static void Main() + { + } + } +} + diff --git a/p02_Fondamentaux/ex_003_001_Main/ex_003_001_Main.csproj b/p02_Fondamentaux/ex_003_001_Main/ex_003_001_Main.csproj new file mode 100644 index 0000000..c585071 --- /dev/null +++ b/p02_Fondamentaux/ex_003_001_Main/ex_003_001_Main.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_003_001_Main + Exe + ex_003_001_Main + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_003_002_Main_HelloWorld/Program.cs b/p02_Fondamentaux/ex_003_002_Main_HelloWorld/Program.cs new file mode 100644 index 0000000..97456f8 --- /dev/null +++ b/p02_Fondamentaux/ex_003_002_Main_HelloWorld/Program.cs @@ -0,0 +1,27 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-21 +// +// ======================================================================== + +//Ici, nous avons besoin de using System; car la classe Console est dans l'espace de noms System. +using System; +using static System.Console; + +//Ce programme affiche "Coucou le monde !" dans la console. +namespace ex_003_002_Main_HelloWorld +{ + class Program + { + //aucun argument + static void Main() + { + WriteLine("Coucou le monde !"); + } + } +} diff --git a/p02_Fondamentaux/ex_003_002_Main_HelloWorld/ex_003_002_Main_HelloWorld.csproj b/p02_Fondamentaux/ex_003_002_Main_HelloWorld/ex_003_002_Main_HelloWorld.csproj new file mode 100644 index 0000000..efd2c41 --- /dev/null +++ b/p02_Fondamentaux/ex_003_002_Main_HelloWorld/ex_003_002_Main_HelloWorld.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_003_002_Main_HelloWorld + Exe + ex_003_002_Main_HelloWorld + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_003_003_Main_arguments/Program.cs b/p02_Fondamentaux/ex_003_003_Main_arguments/Program.cs new file mode 100644 index 0000000..afc94ca --- /dev/null +++ b/p02_Fondamentaux/ex_003_003_Main_arguments/Program.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-21 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_003_003_Main_arguments +{ + class Program + { + //les arguments sont passés dans un tableau de chaîne de caractères + static void Main(string[] args) + { + Console.OutputEncoding = System.Text.Encoding.UTF8; + + WriteLine("Coucou le monde !"); + + //on peut en savoir le nombre en utilisant la propriété Length + //ici, {0} sera remplacé par la valeur de args.Length + WriteLine($"Vous avez passé {args.Length} argument(s)."); + + WriteLine("Voici les arguments que vous avez passés :"); + + //foreach permet de parcourir les éléments de ce tableau d'arguments + foreach (string arg in args) + { + // \t permet d'insérer une tabulation + //ici, {0} sera remplacé par la valeur de arg + WriteLine($"\t{arg}"); + } + } + } +} diff --git a/p02_Fondamentaux/ex_003_003_Main_arguments/Properties/launchSettings.json b/p02_Fondamentaux/ex_003_003_Main_arguments/Properties/launchSettings.json new file mode 100644 index 0000000..32a0c35 --- /dev/null +++ b/p02_Fondamentaux/ex_003_003_Main_arguments/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "ex_003_003_Main_arguments": { + "commandName": "Project", + "commandLineArgs": "I love C# and .NET Core" + } + } +} \ No newline at end of file diff --git a/p02_Fondamentaux/ex_003_003_Main_arguments/ReadMe.md b/p02_Fondamentaux/ex_003_003_Main_arguments/ReadMe.md new file mode 100644 index 0000000..486cc29 --- /dev/null +++ b/p02_Fondamentaux/ex_003_003_Main_arguments/ReadMe.md @@ -0,0 +1,19 @@ +## How to change the arguments passed to the Main method? + +##### Method 1: +- Access the properties of the project (right click on the Project file -> Properties). +- Access the debug tab +- You can now change the application arguments! +##### Method 2: +- Change the launchSettings.json file in Properties under the project file +- to (for instance): +``` json +{ + "profiles": { + "ex_003_003_Main_arguments": { + "commandName": "Project", + "commandLineArgs": "I love C# and .NET Core" + } + } +} +``` \ No newline at end of file diff --git a/p02_Fondamentaux/ex_003_003_Main_arguments/ex_003_003_Main_arguments.csproj b/p02_Fondamentaux/ex_003_003_Main_arguments/ex_003_003_Main_arguments.csproj new file mode 100644 index 0000000..32b35bd --- /dev/null +++ b/p02_Fondamentaux/ex_003_003_Main_arguments/ex_003_003_Main_arguments.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_003_003_Main_arguments + Exe + ex_003_003_Main_arguments + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_003_004_Console/Program.cs b/p02_Fondamentaux/ex_003_004_Console/Program.cs new file mode 100644 index 0000000..c490af5 --- /dev/null +++ b/p02_Fondamentaux/ex_003_004_Console/Program.cs @@ -0,0 +1,103 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-21 +// +// ======================================================================== + +using System; +using static System.Console; +using static System.Text.Encoding; + +namespace ex_003_004_Console +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = UTF8; + + WriteLine("Voici un exemple d'utilisation de la console"); + + //utilisation de Write, qui écrit dans la Console, mais ne va pas à la ligne + Write("Avec Write, je ne vais pas à la ligne, "); + + //WriteLine, écrit dans la Console, puis va à la ligne + WriteLine("mais avec Write Line, si."); + + //toutes les variables peuvent être transformées en chaîne de caractères, + //car chaque type possède une méthode ToString() qui le transforme en chaîne de caractères. + //Dans le cas des types que vous créerez vous-même, vous devrez écrire cette méthode ToString, + //car la méthode par défaut ne vous conviendra pas souvent. + //Dans le cas des types .NET, vous pouvez l'utiliser directement, car elle toujours réécrite. + //Lorsque vous voulez afficher une variable dans la Console à l'aide de Write ou WriteLine, + //vous pouvez appeler explicitement ce ToString, ou ne rien faire, dans ce cas, ToString est appelée + //de manière implicite. + WriteLine("Je peux aussi écrire le contenu de variables : "); + int a = 2; + //les deux lignes suivantes font exactement la même chose (la première est juste plus simple) + WriteLine(a); + WriteLine(a.ToString()); + int b = 3; + int c = a + b; + //dans la ligne suivante, le compilateur fait a.ToString() + " + " b.ToString() + " = " + c.ToString() + //car il commence par le premier + : a + " + " + //Lorsque le compilateur cherche à ajouter un entier à une chaîne de caractères, il transforme l'entier en chaîne de caractères + //puis concatène les deux. + //Il obtient donc la chaîne de caractères "2 + ", puis passe à la seconde opération : une chaîne de caractères + un entier + //Il transforme donc l'entier en chaîne de caractères et les concatène, etc... + WriteLine(a + " + " + b + " = " + c); + //Autre manière plus simple de l'écrire, et plus efficace, en utilisant un string.Format implicite + //(qui sera présenté plus tard) + WriteLine("{0} + {1} = {2}", a, b, c); + //ou encore depuis C#6 : + WriteLine($"{a} + {b} = {c}"); + + //à partir de ce que vous avez vu dans l'exemple précédent, essayez de déterminer le résultat des affichages suivants : + WriteLine("petit truc marrant :"); + WriteLine(a + b + " = Somme"); + WriteLine("Somme = " + a + b); + //le premier donne "5 = Somme" et le deuxième donne "Somme = 23" + //Dans le premier cas, le compilateur s'occupe du premier + : a + b + //a et b sont deux entiers, il ajoute donc deux entiers : 2 + 3 = 5 + //puis il ajoute un entier (5) et une chaîne de caractères " = Somme" + //Il transforme donc l'entier en chaîne de caractères puis les concatène : "5 = Somme" + //Dans le deuxième cas, il ajoute d'abord une chaîne de caractères "Somme = " et un entier a + //Il transforme donc l'entier en chaîne de caractères et les concatène, soit "Somme = " + "2" = "Somme = 2" + //Il ajoute ensuite une chaîne de caractères "Somme = 2" et un entier b + //Il transforme donc l'entier en chaîne de caractères "3" et les concatène : "Somme = 2" + "3" = "Somme = 23" + + WriteLine("Ecrivez du texte puis appuyez sur Entrée"); + //pour lire le texte entré par l'utilisateur + string s = ReadLine(); //lit jusqu'à l'appui sur ENTREE + WriteLine($"Vous avez écrit : {s}"); + //attend l'appui sur une touche + ReadKey(true); + + + + //on peut changer la couleur de fond + BackgroundColor = ConsoleColor.DarkBlue; + + //on peut changer la couleur du texte + ForegroundColor = ConsoleColor.Yellow; + WriteLine("sympa mais vite illisible :)"); + + //on peut faire des beep + Beep(); + + + //on peut obtenir des informations sur la Console, comme sa taille par exemple + WriteLine($"La fenêtre Console mesure {WindowHeight} caractères de haut et {WindowWidth} caractères de large"); + + //On peut effacfer le contenu de la Console avec Clear + WriteLine("Appuyez sur une touche pour effacer le contenu de la Console"); + ReadKey(true); + Clear(); + } + } +} diff --git a/p02_Fondamentaux/ex_003_004_Console/ex_003_004_Console.csproj b/p02_Fondamentaux/ex_003_004_Console/ex_003_004_Console.csproj new file mode 100644 index 0000000..2ae8389 --- /dev/null +++ b/p02_Fondamentaux/ex_003_004_Console/ex_003_004_Console.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_003_004_Console + Exe + ex_003_004_Console + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_001_TypesNumeriques/Program.cs b/p02_Fondamentaux/ex_004_001_TypesNumeriques/Program.cs new file mode 100644 index 0000000..c090c05 --- /dev/null +++ b/p02_Fondamentaux/ex_004_001_TypesNumeriques/Program.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// Mise à jour : 2017-10-03 +// +// ======================================================================== + +using static System.Console; +using static System.Text.Encoding; + +namespace ex_004_001_TypesNumeriques +{ + class Program + { + /// + /// Dans cet exemple, plusieurs variables de différents types sont présentées. Notez qu'un constante + /// de type float nécessite un f pour être différenciée d'un double + /// + /// + static void Main(string[] args) + { + OutputEncoding = UTF8; + + //types entiers + byte b; //variable codée sur un octet (n'importe quelle valeur entre 0 et 255) + sbyte sb; //variable codée sur un octet mais signée (n'importe quelle valeur entre -128 et 127) + short sh; //entier signé sur 16 bits. de -32768 à 32767 (automatiquement converti en int pendant une opération arithmétique) + ushort ush; //idem short, mais non signé : de 0 à 65535 + int i; //entier codé sur 32 bits. + i = 10; + uint ui; //entier non signé codé sur 32 bits. + long l; //entier signé codé sur 64 bits. + l = 10L; + ulong ul; //entier non signé codé sur 64 bits. + + //types réels + float f; //codé sur 32 bits + f = 4.5f; + double d; //codé sur 64 bits + d = 4.5; + decimal dec; //codé sur 128 bits, spécialement créé pour les applications financières. Plus précis mais 10 fois plus lent. + dec = 1.2m; + + //le qualificatif const permet de garantir qu'une "variable" ne sera pas modifiée + const int ci = 3; + + //membres des types numériques + WriteLine($"int.MinValue = {int.MinValue}"); + WriteLine($"int.MaxValue = {int.MaxValue}"); + WriteLine($"float.MinValue = {float.MinValue}"); + WriteLine($"float.MaxValue = {float.MaxValue}"); + WriteLine($"float.Epsilon = {float.Epsilon}"); + WriteLine($"float.NegativeInfinity = {float.NegativeInfinity}"); + WriteLine($"float.PositiveInfinity = {float.PositiveInfinity}"); + + //valeurs par défaut : + //numerique : 0 + + + //Depuis C# 7.0, il y a eu quelques améliorations dans l'écriture des constantes numériques : + // - on peut maintenant utiliser l'underscore _ pour améliorer la lisibilité des grands nombres : + d = 123_456_789; + WriteLine(d); + + // - on peut également l'utiliser sur les valeurs en hexadécimal : + d = 0x7_5B_CD_15; + WriteLine(d); + + // - et également sur les nombres en binaire, ce qui peut éviter d'avoir à apprendre le nombre en hexadécimal :) + d = 0b111_0101_1011_1100_1101_0001_0101; + WriteLine(d); + } + } +} diff --git a/p02_Fondamentaux/ex_004_001_TypesNumeriques/ex_004_001_TypesNumeriques.csproj b/p02_Fondamentaux/ex_004_001_TypesNumeriques/ex_004_001_TypesNumeriques.csproj new file mode 100644 index 0000000..a2bc3bf --- /dev/null +++ b/p02_Fondamentaux/ex_004_001_TypesNumeriques/ex_004_001_TypesNumeriques.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_001_TypesNumeriques + Exe + ex_004_001_TypesNumeriques + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_002_Math/Program.cs b/p02_Fondamentaux/ex_004_002_Math/Program.cs new file mode 100644 index 0000000..7220464 --- /dev/null +++ b/p02_Fondamentaux/ex_004_002_Math/Program.cs @@ -0,0 +1,99 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_004_002_Math +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //constantes de la classe Math : + WriteLine($"CONSTANTES DE LA CLASSE MATH"); + //epsilon + WriteLine($"E(e) : {Math.E}"); + //PI + WriteLine($"Pi : {Math.PI}"); + + WriteLine(); + + //méthodes pour arrondir + WriteLine($"METHODES POUR ARRONDIR"); + //arrondir + WriteLine($"Arrondir 1,9876 à 2 chiffres après la virgule : {Math.Round(1.9876, 2)}"); + //tronquer + WriteLine($"Partie entière de 1,9876 : {Math.Truncate(1.9876)}"); + //plus grand entier inférieur + WriteLine($"Plus grand entier inférieur de 1,9876 : {Math.Floor(1.9876)}"); + //plus petit entier supérieur + WriteLine($"Plus petit entier supérieur de 1,9876 : {Math.Ceiling(1.9876)}"); + + WriteLine(); + + //calcul de maximums et minimums + WriteLine($"maximum entre 6 et 4 : {Math.Max(6, 4)}"); + WriteLine($"minimum entre 6 et 4 : {Math.Min(6, 4)}"); + WriteLine($"maximum entre 6, 4 et 5 : {Math.Max(Math.Max(6, 4), 5)}"); //on peut faire mieux avec LINQ et les collections + + WriteLine(); + + //signes et valeurs absolues + WriteLine($"valeur absolue de -4,567 : {Math.Abs(-4.567)}"); + WriteLine($"signe de -4.567 : {Math.Sign(-4.567)}"); + + WriteLine(); + + //racines carrées, puissances, exponentielles et logarithmes + WriteLine($"Racine carrée de 625 : {Math.Sqrt(625)}"); + WriteLine($"8 à la puissance 3 : {Math.Pow(8, 3)}"); + WriteLine($"exponentielle de 1 (Exp(1)) : {Math.Exp(1)}"); + WriteLine($"logarithme népérien de e (ln(e)) : {Math.Log(Math.E)}"); + WriteLine($"logarithme décimal de 10 (log(10)) : {Math.Log10(10)}"); + + WriteLine(); + + //trigonométrie + WriteLine($"sin(pi/2) : {Math.Sin(Math.PI / 2)}"); + WriteLine($"cos(pi/2) : {Math.Cos(Math.PI / 2)}"); + WriteLine($"tan(pi/2) : {Math.Tan(Math.PI / 2)}"); + //il existe aussi : le sinus hyperbolique (Sinh), le cosinus hyperbolique (Cosh), la tangente hyperbolique (Tanh) + // arcsinus (Asin), arccosinus (Acos) et arctan (Atan) + + WriteLine(); + + //autres exemples : + WriteLine($"exp(e) = {Math.Exp(Math.E)}"); + WriteLine($"ln(exp(1)) = {Math.Log(Math.Exp(1))}"); + WriteLine($"sqrt(|cos(1)|) = {Math.Sqrt(Math.Abs(Math.Cos(1)))}"); + + WriteLine(); + + //L'assemblage System.Numerics.dll introduit également deux nouvelles classes : + // BigInteger : un très grand entier sans perte de précision + // Complex : une structure représentant un nombre complexe + System.Numerics.BigInteger carlos = System.Numerics.BigInteger.Pow(2, 200); + WriteLine($"2 à la puissance 200 :\n{carlos}"); + + System.Numerics.Complex complex = new System.Numerics.Complex(2, 3); + System.Numerics.Complex complex2 = new System.Numerics.Complex(-5, 2); + WriteLine($"Partie réelle de complex : {complex.Real} / partie imaginaire de complex : {complex.Imaginary}"); + //les opérateurs sont réécrits pour les nombres complexes + System.Numerics.Complex complex3 = complex + complex2; + WriteLine($"(2 + 3i) + (-5 + 2i) = ({complex3.Real} + {complex3.Imaginary}i)"); + complex3 = System.Numerics.Complex.Conjugate(complex); + WriteLine($"conjugué de (2 + 3i) = ({complex3.Real} + {complex3.Imaginary}i)"); + } + } +} diff --git a/p02_Fondamentaux/ex_004_002_Math/ex_004_002_Math.csproj b/p02_Fondamentaux/ex_004_002_Math/ex_004_002_Math.csproj new file mode 100644 index 0000000..b64a15c --- /dev/null +++ b/p02_Fondamentaux/ex_004_002_Math/ex_004_002_Math.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_002_Math + Exe + ex_004_002_Math + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_003_Random/Program.cs b/p02_Fondamentaux/ex_004_003_Random/Program.cs new file mode 100644 index 0000000..929047e --- /dev/null +++ b/p02_Fondamentaux/ex_004_003_Random/Program.cs @@ -0,0 +1,47 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_004_003_Random +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //juste pour que la fenêtre soit plus large et que le texte soit en conséquence plus lisible + WindowWidth += 5; + + //Random crée une suite de nombre aléatoires en fonction d'une graine (seed) + Random rdm1 = new Random(); //utilise l'heure actuelle pour créer le seed automatiquement + //si vous relancez plusieurs fois le programme, le nombre va changer car l'heure varie. + WriteLine($"rdm1 : {rdm1.Next(20)} {rdm1.Next(20)} {rdm1.Next(20)} {rdm1.Next(20)} {rdm1.Next(20)}"); + + WriteLine(); + + //utilise le seed donné en paramètre + //la suite de nombres est donc toujours la même + //si vous relancez plusieurs fois le programme, vous aurez toujours la même suite de nombres. + //ce peut être utile pour recréer les mêmes conditions lors d'un debug + Random rdm2 = new Random(102394753); + WriteLine($"rdm2 : {rdm2.Next(20)} {rdm2.Next(20)} {rdm2.Next(20)} {rdm2.Next(20)} {rdm2.Next(20)}"); + + //différentes façons d'utiliser la classe Random + WriteLine($"rdm1.Next() retourne un nombre entier aléatoire non négatif :\n{rdm1.Next()}\n"); + WriteLine($"rdm1.Next(20) retourne un nombre entier aléatoire dans l'intervalle [0;20[ :\n{rdm1.Next(20)}\n"); + WriteLine($"rdm1.Next(5,20) retourne un nombre entier aléatoire dans l'intervalle [5;20[ :\n{rdm1.Next(5, 20)}\n"); + WriteLine($"rdm1.NextDouble() retourne un nombre réel aléatoire dans l'intervalle [0.0;1.0[ :\n{rdm1.NextDouble()}\n"); + } + } +} diff --git a/p02_Fondamentaux/ex_004_003_Random/ex_004_003_Random.csproj b/p02_Fondamentaux/ex_004_003_Random/ex_004_003_Random.csproj new file mode 100644 index 0000000..7651246 --- /dev/null +++ b/p02_Fondamentaux/ex_004_003_Random/ex_004_003_Random.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_003_Random + Exe + ex_004_003_Random + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_004_TypeBool/Program.cs b/p02_Fondamentaux/ex_004_004_TypeBool/Program.cs new file mode 100644 index 0000000..088c5a2 --- /dev/null +++ b/p02_Fondamentaux/ex_004_004_TypeBool/Program.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using static System.Console; + +namespace ex_004_004_TypeBool +{ + class Program + { + static void Main(string[] args) + { + //type booléen + bool boolean; //true ou false + + boolean = true; + WriteLine($"true : {true}"); + WriteLine($"false : {false}"); + + WriteLine($"FalseString : {bool.FalseString}"); + WriteLine($"TrueString : {bool.TrueString}"); + } + } +} diff --git a/p02_Fondamentaux/ex_004_004_TypeBool/ex_004_004_TypeBool.csproj b/p02_Fondamentaux/ex_004_004_TypeBool/ex_004_004_TypeBool.csproj new file mode 100644 index 0000000..e24abce --- /dev/null +++ b/p02_Fondamentaux/ex_004_004_TypeBool/ex_004_004_TypeBool.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_004_TypeBool + Exe + ex_004_004_TypeBool + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_005_TypeChar/Program.cs b/p02_Fondamentaux/ex_004_005_TypeChar/Program.cs new file mode 100644 index 0000000..d7e86cb --- /dev/null +++ b/p02_Fondamentaux/ex_004_005_TypeChar/Program.cs @@ -0,0 +1,76 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using static System.Console; + +namespace ex_004_005_TypeChar +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //type char + char c; //codé sur 16 bits ( != du C++ ), caractère du système Unicode + c = 'A'; + c = '\x41'; //0x41 (ou 65 en décimal) dans Unicode. lettre A + c = (char)65; //idem + c = '\u0041'; //idem + //quelques caractères utiles + c = '\n'; //à la ligne + c = '\t'; //tabulation horizontale + c = '\v'; //tabulation verticale + c = '\\'; //backslash + c = '\''; //single quote + c = '\"'; //double quote + c = '\0'; //null + + //quelques membres du type char : + char a = 'A'; + char deux = '2'; + char virgule = ','; + char blanc = ' '; + //IsDigit : le caractère est-il un chiffre ? + WriteLine($"char.IsDigit('A') ? {char.IsDigit(a)}"); + WriteLine($"char.IsDigit('2') ? {char.IsDigit(deux)}"); + WriteLine($"char.IsDigit(',') ? {char.IsDigit(virgule)}"); + WriteLine($"char.IsDigit(' ') ? {char.IsDigit(blanc)}"); + WriteLine(); + //IsLetter indique s'il s'agit d'une lettre + WriteLine($"char.IsLetter('A') ? {char.IsLetter(a)}"); + WriteLine($"char.IsLetter('2') ? {char.IsLetter(deux)}"); + WriteLine($"char.IsLetter(',') ? {char.IsLetter(virgule)}"); + WriteLine($"char.IsLetter(' ') ? {char.IsLetter(blanc)}"); + //il y a aussi IsLower pour les minuscules, IsUpper pour les majuscules, IsLetterOrDigit pour lettres ou nombres + WriteLine(); + + //IsPunctuation indique s'il s'agit d'un caractère de ponctuation + WriteLine($"char.IsPunctuation('A') ? {char.IsPunctuation(a)}"); + WriteLine($"char.IsPunctuation('2') ? {char.IsPunctuation(deux)}"); + WriteLine($"char.IsPunctuation(',') ? {char.IsPunctuation(virgule)}"); + WriteLine($"char.IsPunctuation(' ') ? {char.IsPunctuation(blanc)}"); + WriteLine(); + + //IsWhiteSpace indique s'il s'agit d'un blanc + WriteLine($"char.IsWhiteSpace('A') ? {char.IsWhiteSpace(a)}"); + WriteLine($"char.IsWhiteSpace('2') ? {char.IsWhiteSpace(deux)}"); + WriteLine($"char.IsWhiteSpace(',') ? {char.IsWhiteSpace(virgule)}"); + WriteLine($"char.IsWhiteSpace(' ') ? {char.IsWhiteSpace(blanc)}"); + WriteLine(); + + //ToUpper et ToLower convertisse en majuscules ou en minuscules. + WriteLine($"char.ToLower('A') = {char.ToLower('A')}"); + WriteLine($"char.ToUpper('a') = {char.ToUpper('a')}"); + WriteLine($"char.ToUpper('é') = {char.ToUpper('é')}"); + } + } +} diff --git a/p02_Fondamentaux/ex_004_005_TypeChar/ex_004_005_TypeChar.csproj b/p02_Fondamentaux/ex_004_005_TypeChar/ex_004_005_TypeChar.csproj new file mode 100644 index 0000000..486f8a6 --- /dev/null +++ b/p02_Fondamentaux/ex_004_005_TypeChar/ex_004_005_TypeChar.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_005_TypeChar + Exe + ex_004_005_TypeChar + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_006_TimeSpan_et_DateTime/Program.cs b/p02_Fondamentaux/ex_004_006_TimeSpan_et_DateTime/Program.cs new file mode 100644 index 0000000..12a76b0 --- /dev/null +++ b/p02_Fondamentaux/ex_004_006_TimeSpan_et_DateTime/Program.cs @@ -0,0 +1,72 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_004_006_TimeSpan_et_DateTime +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //TimeSpan + //construction d'une durée à partir d'un constructeur + TimeSpan durée_d_un_cours = new TimeSpan(1, 50, 00); + //construction d'une durée à partir d'un nombre de minutes (ou heures, ou secondes...) + TimeSpan retard = TimeSpan.FromMinutes(21.20); + //opération (addition, soustraction) de durées + TimeSpan durée_du_cours_aujourd_hui = durée_d_un_cours + retard; + //durée nulle + TimeSpan durée_nulle = TimeSpan.Zero; + //affichage d'une durée + WriteLine($"Le cours d'aujourd'hui est de {durée_d_un_cours} + {retard} de retard = {durée_du_cours_aujourd_hui}"); + WriteLine(); + + //DateTime + //construction d'un DateTime + DateTime débutDeJazzEnTete2012 = new DateTime(2012, 10, 23, 20, 00, 00); + DateTime finDeJazzEnTete2012 = new DateTime(2012, 10, 27, 23, 59, 00); + //soustraction de DateTime + TimeSpan duréeDeJazzEnTete2012 = finDeJazzEnTete2012.Subtract(débutDeJazzEnTete2012); + //affichage de DateTime + WriteLine($"Le festival jazz en tête a duré : {duréeDeJazzEnTete2012}"); + WriteLine($"Le festival jazz en tête a duré : {duréeDeJazzEnTete2012.Days} jours et {duréeDeJazzEnTete2012.Hours} heures"); + WriteLine($"Le festival jazz en tête a duré : {duréeDeJazzEnTete2012.Days} jours et {Math.Round(duréeDeJazzEnTete2012.TotalHours - (duréeDeJazzEnTete2012.Days * 24))} heures"); + //on peut ajouter ou soustraire du temps à 1 DateTime + DateTime débutDernierConcert = finDeJazzEnTete2012 - TimeSpan.FromHours(4); + //autre solution équivalente + débutDernierConcert = finDeJazzEnTete2012.Subtract(TimeSpan.FromHours(4)); + WriteLine($"Le dernier concert de Jazz en Tete commence le : {débutDernierConcert.ToString("dd/MM/yyy")} à {débutDernierConcert.ToString("hh:mm")}"); + + WriteLine(); + + //gestion des décalages horaires + DateTime début_de_la_finale_de_l_USOpen = new DateTime(2010, 09, 13, 20, 00, 00, DateTimeKind.Utc); + WriteLine($"La finale commencera : {début_de_la_finale_de_l_USOpen.ToLocalTime().ToString("f")} chez nous"); + WriteLine($"La finale commencera : {(début_de_la_finale_de_l_USOpen - TimeSpan.FromHours(4)).ToString("g")} à New York"); + WriteLine(); + + //on peut parser une chaîne de caractères ! + string date_réjouissances = "jeudi 29 septembre 2011 13:30"; + WriteLine("Convertir jeudi 29 septembre 2011 13:30 en DateTime ? oui bien sûr !"); + DateTime réjouissances = DateTime.Parse(date_réjouissances); + WriteLine(réjouissances); + + //la date et l'heure actuelles (au moment de l'exécution de la ligne) + //est donnée par : + DateTime maintenant = DateTime.Now; + WriteLine($"Maintenant : {maintenant}"); + } + } +} diff --git a/p02_Fondamentaux/ex_004_006_TimeSpan_et_DateTime/ex_004_006_TimeSpan_et_DateTime.csproj b/p02_Fondamentaux/ex_004_006_TimeSpan_et_DateTime/ex_004_006_TimeSpan_et_DateTime.csproj new file mode 100644 index 0000000..603e013 --- /dev/null +++ b/p02_Fondamentaux/ex_004_006_TimeSpan_et_DateTime/ex_004_006_TimeSpan_et_DateTime.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_006_TimeSpan_et_DateTime + Exe + ex_004_006_TimeSpan_et_DateTime + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_007_DureeDeVie/Program.cs b/p02_Fondamentaux/ex_004_007_DureeDeVie/Program.cs new file mode 100644 index 0000000..c7d42a0 --- /dev/null +++ b/p02_Fondamentaux/ex_004_007_DureeDeVie/Program.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using System; + + +namespace ex_004_007_DureeDeVie +{ + class Program + { + static void Main(string[] args) + { + int a = 2;//la pile contient ... a + + int b = 3;//la pile contient ... a b + + float f = 10;//la pile contient ... a b f + + { + int c = a + b; //la pile contient ... a b f c + f /= c; //f est modifié, la pile contient ... a b f c + }//c meurt ici, la pile contient ... a b f + + TimeSpan ts = TimeSpan.FromHours(2); //la pile contient ... a b f ts + + { + TimeSpan ts2 = ts - TimeSpan.FromHours(1); //la pile contient ... a b f ts ts2 + }//ts2 meurt ici, la pile contient ... a b f ts + + + }//a, b, f, ts meurent ici, la pile contient ... + } +} diff --git a/p02_Fondamentaux/ex_004_007_DureeDeVie/ex_004_007_DureeDeVie.csproj b/p02_Fondamentaux/ex_004_007_DureeDeVie/ex_004_007_DureeDeVie.csproj new file mode 100644 index 0000000..f05ad23 --- /dev/null +++ b/p02_Fondamentaux/ex_004_007_DureeDeVie/ex_004_007_DureeDeVie.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_007_DureeDeVie + Exe + ex_004_007_DureeDeVie + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_008_var/Program.cs b/p02_Fondamentaux/ex_004_008_var/Program.cs new file mode 100644 index 0000000..81e90b5 --- /dev/null +++ b/p02_Fondamentaux/ex_004_008_var/Program.cs @@ -0,0 +1,29 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_004_008_var +{ + class Program + { + static void Main(string[] args) + { + //var : mot clé pour déclarer en même temps qu'on initialise une variable + //le type est automatiquement choisi + var var1 = 5; // est équivalent à int var1 = 5; + WriteLine($"le type de var1 est {var1.GetType()}"); + var var2 = "coucou"; // est équivalent à string var2 = "coucou"; + WriteLine($"le type de var2 est {var2.GetType()}"); + } + } +} diff --git a/p02_Fondamentaux/ex_004_008_var/ex_004_008_var.csproj b/p02_Fondamentaux/ex_004_008_var/ex_004_008_var.csproj new file mode 100644 index 0000000..61c83e9 --- /dev/null +++ b/p02_Fondamentaux/ex_004_008_var/ex_004_008_var.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_008_var + Exe + ex_004_008_var + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_004_009_Tuple/Program.CSharp7.cs b/p02_Fondamentaux/ex_004_009_Tuple/Program.CSharp7.cs new file mode 100644 index 0000000..ce96422 --- /dev/null +++ b/p02_Fondamentaux/ex_004_009_Tuple/Program.CSharp7.cs @@ -0,0 +1,92 @@ +// ======================================================================== +// +// Copyright (C) 2017-2018 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.CSharp7.cs +// Author : Marc Chevaldonné +// Creation date : 2017-09-19 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_004_009_Tuple +{ + partial class Program + { + /// + /// Le constat sur l'utilisation des Tuples jusqu'à C# 6.0 est le suivant : + /// - l'utilisation des paramètres out (a priori rien à voir avec les Tuples), n'est pas pratique et lourd et ils ne marchent pas avec les méthodes asynchrones + /// - l'utilisation des Tuples est verbeuse et l'allocation est lourde + /// - ceci entraine beaucoup d'écriture de code pour des variables à durée de vie parfois très limitée + /// + /// C# 7.0 ajoute donc les types Tuple et des sucres syntaxiques pour améliorer tout ceci ... : + /// + static void NouveautésCSharp7() + { + //La méthode suivante rend directement trois variables en un "tuple value" : un string, et deux int + //ATTENTION : ceci n'est utilisable que si vous ajoutez le package NuGet System.TupleValue + (string, int, int) NounoursData(Nounours nounours) + { + return (nounours.Nom, nounours.NbPoils, nounours.Naissance.Year); + } + //pour utiliser le résultat de la méthode ci-dessous, vous pouvez tout stocker dans une seule variable var (de type Tuple ici) : + var test = NounoursData(new Nounours { Nom = "Gizmo", NbPoils = 123456789, Naissance = new DateTime(1984, 6, 8) }); + //et accéder aux différentes valeurs avec Item1, Item2, Item3... + WriteLine($"{test.Item1} ; {test.Item2} ; {test.Item3}"); + + //un des problèmes des Tuples, c'est que Item1, Item2, Item3... ce n'est pas très parlant. On peut donc réécrire la méthode + //de la manière suivante, en donnant un nom aux valeurs de retour : + (string nom, int nbPoils, int annéeDeNaissance) NounoursData2(Nounours nounours) + { + return (nounours.Nom, nounours.NbPoils, nounours.Naissance.Year); + //cette dernière ligne peut aussi s'écrire : + //return (nom: nounours.Nom, nbPoils: nounours.NbPoils, annéeDeNaissance: nounours.Naissance.Year); + //au cas où vous ne calculeriez pas les éléments dans le bon ordre + } + //l'accès aux résultats reste inchangé : + var test2 = NounoursData2(new Nounours { Nom = "Gizmo", NbPoils = 123456789, Naissance = new DateTime(1984, 6, 8) }); + //par contre, on n'utilise plus Item1, Item2, Item3, mais les noms utilisés en retour de la méthode (ici nom, nbPoils et annéeDeNaissance) + WriteLine($"{test2.nom} ; {test2.nbPoils} ; {test2.annéeDeNaissance}"); + + //notez que les noms n'ont pas d'autre intérêt que de simplifier l'utilisation. C'est le type des éléments des Tuples qui permet de comparer deux Tuples. + + + //DECONSTRUCTION + //La deconstruction est une syntaxe pour diviser un tuple (ou un autre type) en ses différents éléments en de nouvelles variables individuelles + //ci-dessous, au lieu de stocker le retour de la méthode NounoursData précédente dans un Tuple, on le stocker dans une Tuple "déconstruit" + (string nom, int nbPoils, int année) = NounoursData(new Nounours { Nom = "Gizmo", NbPoils = 123456789, Naissance = new DateTime(1984, 6, 8) }); + WriteLine($"{nom} ; {nbPoils} ; {année}"); + + //on peut aussi utiliser var comme d'habitude + (var nom2, var nbPoils2, var année2) = NounoursData(new Nounours { Nom = "Gizmo", NbPoils = 123456789, Naissance = new DateTime(1984, 6, 8) }); + WriteLine($"{nom2} ; {nbPoils2} ; {année2}"); + + //ou bien utiliser var devant le tuple literal + var (nom3, nbPoils3, année3) = NounoursData(new Nounours { Nom = "Gizmo", NbPoils = 123456789, Naissance = new DateTime(1984, 6, 8) }); + WriteLine($"{nom3} ; {nbPoils3} ; {année3}"); + + //ou encore déconstruire dans des variables existantes : + string nom4; + int nbPoils4, année4; + (nom4, nbPoils4, année4) = NounoursData(new Nounours { Nom = "Gizmo", NbPoils = 123456789, Naissance = new DateTime(1984, 6, 8) }); + WriteLine($"{nom4} ; {nbPoils4} ; {année4}"); + + //Notez qu'on peut déconstruire autre chose que des Tuples (cf. ex_ + } + } + + class Nounours + { + public string Nom { get; set; } + public int NbPoils { get; set; } + public DateTime Naissance { get; set; } + + public override string ToString() + { + return $"{Nom} a {NbPoils} poils et est né en {Naissance.Year}"; + } + } +} diff --git a/p02_Fondamentaux/ex_004_009_Tuple/Program.cs b/p02_Fondamentaux/ex_004_009_Tuple/Program.cs new file mode 100644 index 0000000..497fed2 --- /dev/null +++ b/p02_Fondamentaux/ex_004_009_Tuple/Program.cs @@ -0,0 +1,61 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// Updated : 2017-09-19 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_004_009_Tuple +{ + partial class Program + { + /// + /// la classe Tuple est générique (voir chapitre 22) et permet de stocker plusieurs références ou valeurs de différents types. + /// Tuple est notamment très pratique pour avoir plusieurs retours de méthodes. + /// Tuple possède des propriétés (voir chapitre 16) en lecture seule permettant d'accéder aux différents éléments du Tuple. + /// Par exemple, si on déclare Tuple, alors Item1 permet d'accéder au string, Item2 à l'int, Item3 au float. + /// + /// Les Tuples sont des types "valeur" et leurs éléments sont publics et mutables. Ils implémentent le protocole d'égalité des types "valeur", + /// i.e. 2 Tuples sont égaux (et ont le même hash code) si et seulement si leurs éléments sont égaux deux à deux (et ont le même hashcode). + /// Ceci rend les Tuples très utiles dans de nombreuses situations. Par exemple : + /// - un dictionnaire avec plusieurs clés : utilisez un tuple comme clef + /// - une liste avec plusieurs valeurs à chaque indice : utilisez un tuple + /// + /// Depuis, C#7.0, il y a eu de nombreux ajouts aux Tuples (voir le 2ème fichier : Program.CSharp7.cs) + /// + /// + static void Main(string[] args) + { + //création d'un Tuple + Tuple tuple = new Tuple("ObiWan Kenobi", 4, 3.2f); + Tuple tuple2 = Tuple.Create("ObiWan Kenobi", 4, 3.2f); + + WriteLine($"{tuple.Item1} {tuple.Item2} {tuple.Item3}"); + + WriteLine(); + int a = 3; + var result = DoubleEtTriple(a); + WriteLine($"le double et le triple de {a} sont {result.Item1} et {result.Item2}"); + + NouveautésCSharp7(); + } + + /// + /// une méthode qui rend le double et le triple d'un nombre + /// + /// nombre à doubler et tripler + /// le double et le triple du nombre + static Tuple DoubleEtTriple(int a) + { + return Tuple.Create(a * 2, a * 3); + } + } +} diff --git a/p02_Fondamentaux/ex_004_009_Tuple/ex_004_009_Tuple.csproj b/p02_Fondamentaux/ex_004_009_Tuple/ex_004_009_Tuple.csproj new file mode 100644 index 0000000..06dac6d --- /dev/null +++ b/p02_Fondamentaux/ex_004_009_Tuple/ex_004_009_Tuple.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_004_009_Tuple + Exe + ex_004_009_Tuple + 6.0.6 + false + false + false + + + + + diff --git a/p02_Fondamentaux/ex_004_010_GuidStruct/Program.cs b/p02_Fondamentaux/ex_004_010_GuidStruct/Program.cs new file mode 100644 index 0000000..93dfa5a --- /dev/null +++ b/p02_Fondamentaux/ex_004_010_GuidStruct/Program.cs @@ -0,0 +1,37 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_004_010_GuidStruct +{ + class Program + { + /// + /// la structure (voir chapitre 20) Guid permet de définir des indentifiants presque uniques. + /// Lorsque vous générez un de ces identifiants, il est très fort probable qu'il soit unique au monde. + /// Il y a 2 puissance 128 Guid différents. + /// + /// + static void Main(string[] args) + { + Guid g = Guid.NewGuid(); + WriteLine(g); + + Guid g2 = new Guid("{9128de4d-1423-4e08-8ca6-a9effbba1f86}"); + Guid g3 = new Guid("9128de4d14234e088ca6a9effbba1f86"); + WriteLine(g2 == g3); + + WriteLine(Guid.Empty); + } + } +} diff --git a/p02_Fondamentaux/ex_004_010_GuidStruct/ex_004_010_GuidStruct.csproj b/p02_Fondamentaux/ex_004_010_GuidStruct/ex_004_010_GuidStruct.csproj new file mode 100644 index 0000000..067f640 --- /dev/null +++ b/p02_Fondamentaux/ex_004_010_GuidStruct/ex_004_010_GuidStruct.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_004_010_GuidStruct + Exe + ex_004_010_GuidStruct + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_005_001_tableaux/Program.cs b/p02_Fondamentaux/ex_005_001_tableaux/Program.cs new file mode 100644 index 0000000..e600434 --- /dev/null +++ b/p02_Fondamentaux/ex_005_001_tableaux/Program.cs @@ -0,0 +1,115 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_005_001_tableaux +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + WindowHeight = LargestWindowHeight; + + //DECLARATION ET ALLOCATION DYNAMIQUE DE LA MEMOIRE + int[] tab; //tab est une référence. Ici, on sait juste que tab désignera un tableau d'entiers à 1 dimension. Ce n'est pas ici + //qu'on indique la taille. tab étant une référence, il est alloué sur la pile. + + tab = new int[3]; //maintenant on alloue la place en mémoire (ici pour 3 entiers) sur le tas. + // Il s'agit donc d'une allocation dynamique + + // en une seule fois : + int[] tab2 = new int[3]; + + + //ALLOCATION DYNAMIQUE ET INITIALISATION EN MEME TEMPS + int[] tab3; + tab3 = new int[] { 1, 2, 3, 4, 5 }; //on peut aussi spécifier directement les valeurs du tableau. Pas la peine donc de donner + //la taille du tableau dans ce cas. + + //en une seule fois : + int[] tab4 = { 1, 2, 3, 4, 5 }; + + //INITIALISATION AUTOMATIQUE + int[] tab4b = new int[5]; + WriteLine(tab4b[2]); // les types numériques sont initialisés à 0 automatiquement + bool[] tab4c = new bool[100]; + WriteLine(tab4c[53]); // les types bool sont initialisés automatiquement à false + //tous les types références (classes et string par exemple sont initialisés à null) + + + //LIBERATION DE LA MEMOIRE + //la libération est automatique, on n'appelle pas delete. + + //ACCES AUX ELEMENTS DU TABLEAU + //les accès aux cellules du tableau se font comme en C/C++ + int a = tab4[0]; //a vaut 1 + a = tab4[1];//a vaut 2 + a = tab4[2];//a vaut 3 + a = tab4[3];//a vaut 4 + a = tab4[4];//a vaut 5 + + //CONTROLE DES ACCES EN DEHORS DU TABLEAU + //les accès en dehors du tableau sont contrôlées par le runtime + // et provoque des exceptions IndexOutOfRangeException + try + { + WriteLine(tab4[5]); + } + catch (IndexOutOfRangeException) + { + WriteLine("tab4[5] a provoqué une exception"); + } + + //TAILLE DU TABLEAU + //la taille d'un tableau est donnée par la propriété Length + WriteLine($"taille du tableau tab4 : {tab4.Length}"); + + //PARCOURIR LES ELEMENTS D'UN TABLEAU + //avec une boucle for + WriteLine("tab4 : "); + for (int i = 0; i < tab4.Length; i++) + { + WriteLine(tab4[i]); + } + //avec une boucle foreach + foreach (var elt in tab4) + { + WriteLine(elt); + } + + //TABLEAU D'OBJECT + //tableaux avec des cellules de types différents + object[] tab5 = new object[3]; + tab5[0] = 12; //contient un entier + tab5[1] = 3.4f; //contient un réel + tab5[2] = "arf"; //contient une chaîne de caractères + //pour déterminer ensuite le type : + for (int i = 0; i < tab5.Length; i++) + { + Type type = tab5[i].GetType(); + string s = type.Name; + WriteLine(s); + } + //ou pour l'utiliser : + for (int i = 0; i < tab5.Length; i++) + { + if (tab5[i] is int) + { + WriteLine(tab5[i]); + } + } + } + } +} diff --git a/p02_Fondamentaux/ex_005_001_tableaux/ex_005_001_tableaux.csproj b/p02_Fondamentaux/ex_005_001_tableaux/ex_005_001_tableaux.csproj new file mode 100644 index 0000000..201ece5 --- /dev/null +++ b/p02_Fondamentaux/ex_005_001_tableaux/ex_005_001_tableaux.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_005_001_tableaux + Exe + ex_005_001_tableaux + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_005_002_copie_de_tableaux/Program.cs b/p02_Fondamentaux/ex_005_002_copie_de_tableaux/Program.cs new file mode 100644 index 0000000..cf764b6 --- /dev/null +++ b/p02_Fondamentaux/ex_005_002_copie_de_tableaux/Program.cs @@ -0,0 +1,124 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using static System.Console; + +namespace ex_005_002_copie_de_tableaux +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + WindowHeight = LargestWindowHeight; + + + //COPIE DE TABLEAUX + WriteLine("\nCopie de tableaux"); + + //1. copie de références + WriteLine("\nCopie de références\n"); + //préparation des tableaux + int[] tab6 = { 1, 2, 3 }; + int[] tab7 = { 5, 6, 7, 8, 9, 10 }; + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab7"); + foreach (int i in tab7) Write($"{i} "); + WriteLine(); + //recopie des références + WriteLine("tab7 = tab6;"); + tab7 = tab6; //attention, on ne copie que les références ! le contenu est donc partagé ! La preuve : + //affichage des tableaux après copie des références + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab7"); + foreach (int i in tab7) Write($"{i} "); + WriteLine(); + //modification d'une case d'un des tableaux + WriteLine("tab7[1] = 4;"); + tab7[1] = 4; + //affichage des contenus après copie modification d'un des deux tableaux + WriteLine("contenu de tab7"); + foreach (int i in tab7) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + + //2. copie de contenus, méthode 1 : new + CopyTo + WriteLine("\nCopie de contenus, méthode 1\n"); + //préparation des tableaux + int[] tab8 = { 5, 6, 7, 8, 9, 10 }; + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab8"); + foreach (int i in tab8) Write($"{i} "); + WriteLine(); + //recopie des contenus + WriteLine("tab8 = new int[tab6.Length];\ntab6.CopyTo(tab8, 0);"); + tab8 = new int[tab6.Length]; // on alloue la place de tab6 pour tab8 + tab6.CopyTo(tab8, 0); // on recopie le contenu de tab6 dans tab8 (ils ont la même taille à cause de la ligne d'avant, donc tout va bien) + //affichage des résultats + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab8"); + foreach (int i in tab8) Write($"{i} "); + WriteLine(); + //modification d'un des deux tableaux + WriteLine("tab8[1] = 2;"); + tab8[1] = 2; + //affichage des contenus après modification d'un des deux tableaux + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab8"); + foreach (int i in tab8) Write($"{i} "); + WriteLine(); + + //3. copie de contenus, méthode 2 : Clone + WriteLine("\nCopie de contenus, méthode 2\n"); + //préparation des tableaux + int[] tab9 = { 5, 6, 7, 8, 9, 10 }; + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab9"); + foreach (int i in tab9) Write($"{i} "); + WriteLine(); + //clonage des tableaux + WriteLine("tab9 = (int[])tab6.Clone();"); + tab9 = (int[])tab6.Clone(); + //affichage après clonage + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab9"); + foreach (int i in tab9) Write($"{i} "); + WriteLine(); + //modification d'un des deux tableaux + WriteLine("tab9[1] = 2;"); + tab9[1] = 2; + //affichage après modification + WriteLine("contenu de tab6"); + foreach (int i in tab6) Write($"{i} "); + WriteLine(); + WriteLine("contenu de tab9"); + foreach (int i in tab9) Write($"{i} "); + WriteLine(); + } + } +} diff --git a/p02_Fondamentaux/ex_005_002_copie_de_tableaux/ex_005_002_copie_de_tableaux.csproj b/p02_Fondamentaux/ex_005_002_copie_de_tableaux/ex_005_002_copie_de_tableaux.csproj new file mode 100644 index 0000000..3054ca9 --- /dev/null +++ b/p02_Fondamentaux/ex_005_002_copie_de_tableaux/ex_005_002_copie_de_tableaux.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_005_002_copie_de_tableaux + Exe + ex_005_002_copie_de_tableaux + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_005_003_tableaux_multiDimensions/Program.cs b/p02_Fondamentaux/ex_005_003_tableaux_multiDimensions/Program.cs new file mode 100644 index 0000000..9e6cd4d --- /dev/null +++ b/p02_Fondamentaux/ex_005_003_tableaux_multiDimensions/Program.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using static System.Console; + +namespace ex_005_003_tableaux_multiDimensions +{ + class Program + { + static void Main(string[] args) + { + //TABLEAUX A PLUSIEURS DIMENSIONS + int[,] mat = new int[2, 3]; //2 lignes et 3 colonnes + int[,] mat2 = { { 1, 2, 3 }, { 4, 5, 6 } }; + int[,,] tab10;//3 dimensions + //pour copier, on peut utiliser la méthode Clone + //parcours d'un tableau à plusieurs dimensions + WriteLine("\nTABLEAUX A DEUX DIMENSIONS"); + for (int ligne = 0; ligne < mat2.GetLength(0); ligne++) + { + for (int colonne = 0; colonne < mat2.GetLength(1); colonne++) + { + Write($"{mat2[ligne, colonne]} "); + } + WriteLine(); + } + + //TABLEAUX EPARSES + int[][] jagged = new int[3][];//tableaux à trois lignes de tailles différentes + jagged[0] = new int[2]; + jagged[0][0] = 10; + jagged[0][1] = 20; + jagged[1] = new int[4]; + jagged[1][0] = 30; + jagged[1][1] = 40; + jagged[1][2] = 50; + jagged[1][3] = 60; + jagged[2] = new int[3]; + jagged[2][0] = 70; + jagged[2][1] = 80; + jagged[2][2] = 90; + WriteLine("\nTABLEAUX EPARSES"); + for (int ligne = 0; ligne < jagged.GetLength(0); ligne++) + { + for (int colonne = 0; colonne < jagged[ligne].Length; colonne++) + { + Write($"{jagged[ligne][colonne]} "); + } + WriteLine(); + } + //initialisation directe + int[][] jagged2 = new int[][] + { + new int[] {10, 20}, + new int[] {30, 40, 50, 60}, + new int[] {70, 80, 90} + }; + + + } + } +} diff --git a/p02_Fondamentaux/ex_005_003_tableaux_multiDimensions/ex_005_003_tableaux_multiDimensions.csproj b/p02_Fondamentaux/ex_005_003_tableaux_multiDimensions/ex_005_003_tableaux_multiDimensions.csproj new file mode 100644 index 0000000..12596cf --- /dev/null +++ b/p02_Fondamentaux/ex_005_003_tableaux_multiDimensions/ex_005_003_tableaux_multiDimensions.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_005_003_tableaux_multiDimensions + Exe + ex_005_003_tableaux_multiDimensions + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_006_001_string/Program.cs b/p02_Fondamentaux/ex_006_001_string/Program.cs new file mode 100644 index 0000000..be4d5fd --- /dev/null +++ b/p02_Fondamentaux/ex_006_001_string/Program.cs @@ -0,0 +1,182 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_006_001_string +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + WindowHeight = LargestWindowHeight; + WindowWidth += 15; + + WriteLine("STRING : Chaîne de caractères immuable"); + + //construction + WriteLine("CONSTRUCTION"); + string s1 = "Bonjour"; + + //caractères spéciaux avec le caractère d'échappement \ + WriteLine("CARACTERES SPECIAUX"); + string s2 = "\'coucou1\' \"coucou2\" \\coucou3\\"; + WriteLine(s2); + s2 = "nouvelle\nligne"; + WriteLine(s2); + s2 = "retour\rcharriot"; + WriteLine(s2); + s2 = "horizontal\ttab"; + WriteLine(s2); + s2 = "alerte audio \a"; // \a fait un son lorsque le string est affiché + WriteLine(s2); + + //verbatim + WriteLine("\n VERBATIM"); + string s3 = "\\\\server\\machin\\trucmuche\\home"; // chaîne non verbatim, il faut utiliser le caractère d'échappement pour afficher + // les backslashs + WriteLine(s3); + s3 = @"\\server\machin\truchmuche\home"; // chaîne verbatim, les caractères spéciaux sont traités comme les autres + WriteLine(s3); + + //string vide + WriteLine("\n CHAINE DE CARACTERES VIDE"); + string s4 = ""; + WriteLine($"la chaîne de caractères : \"{s4}\" a une longueur de : {s4.Length} caractère(s)"); + //ou + s4 = String.Empty; + WriteLine($"la chaîne de caractères : \"{s4}\" a une longueur de : {s4.Length} caractère(s)"); + WriteLine($"s4 == \"\" ? {s4 == ""}"); + WriteLine($"s4 == String.Empty ? {s4 == string.Empty}"); + WriteLine($"s4.Length == 0 ? {s4.Length == 0}"); + + //string null (string est reference type) + WriteLine("\n CHAINE DE CARACTERES NULLE"); + string s5 = null; + WriteLine($"s5 == \"\" ? {s5 == ""}"); + try + { + WriteLine($"s5.Length == 0 ? {s5.Length == 0}"); + } + catch + { + WriteLine($"s5.Length == 0 ? False"); + } + + WriteLine($"string.IsNullOrEmpty(s4) ? {string.IsNullOrEmpty(s4)}"); + WriteLine($"string.IsNullOrEmpty(s5) ? {string.IsNullOrEmpty(s5)}"); + WriteLine($"string.IsNullOrWhiteSpace(\" \") ? {string.IsNullOrWhiteSpace(" ")}"); + + //accéder et chercher dans les string + WriteLine($"\n RECHERCHER DANS LES STRING"); + string s6 = "barbapapa"; + WriteLine(s6); + WriteLine($"3ème caractère : {s6[2]}"); + WriteLine($"s6.Contains(\"pa\") ? {s6.Contains("pa")}"); + WriteLine($"s6.EndsWith(\"pa\") ? {s6.EndsWith("pa")}"); + WriteLine($"s6.StartsWith(\"ba\") ? {s6.StartsWith("ba")}"); + WriteLine($"s6.IndexOf(\"ba\") ? {s6.IndexOf("ba")}"); + + //manipuler les string + WriteLine($"\n MANIPULER LES STRING"); + WriteLine($"CONCATENATION DE STRING"); + //concatenation de string + string s7 = "Jim" + " " + "Raynor"; + WriteLine($"\"Jim\" + \" \" + \"Raynor\" = \"{s7}\""); + //substring + WriteLine($"SUBSTRING"); + string s8 = s7.Substring(0, 3); + WriteLine($"\"Jim Raynor\".Substring(0, 3) = {s8}"); + s8 = s7.Substring(2, 3); + WriteLine($"\"Jim Raynor\".Substring(2, 3) = {s8}"); + s8 = s7.Substring(5); + WriteLine($"\"Jim Raynor\".Substring(5) = {s8}"); + + //insert, remove, replace, ToUpper, ToLower + WriteLine($"REMOVE"); + s8 = s7.Remove(2, 3); + WriteLine($"\"Jim Raynor\".Remove(2, 3) = {s8}"); + WriteLine($"INSERT"); + s8 = s8.Insert(2, "m R"); + WriteLine($"\"Jiaynor\".Insert(2, \"m R\") = {s8}"); + WriteLine($"REPLACE"); + s8 = "Les chaussettes de l'archiduchesse"; + s8 = s8.Replace(" ", "_"); + WriteLine($"\"Les chaussettes de l'archiduchesse\".Replace(\" \", \"_\") = {s8}"); + WriteLine($"TO UPPER, TO LOWER"); + s8 = s8.ToUpper(); + WriteLine($"\"Les_chaussettes_de_l'archiduchesse\".ToUpper() = {s8}"); + s8 = s8.ToLower(); + WriteLine($"\"LES_CHAUSSETTES_DE_L'ARCHIDUCHESSE\".ToLower() = {s8}"); + + + //PadLeft, PadRight + WriteLine("\n PADLEFT, PADRIGHT, TRIM"); + s8 = s8.PadLeft(50).PadRight(60, '!'); + WriteLine($"\"les_chaussettes_de_l'archiduchesse\".PadLeft(50).PadRight(60, \'!\') = \n{s8}"); + + + //Trim : enlève les blancs (whitespace, tab, new lines...) + s8 = s8.Trim(); //existe aussi avec TrimStart et TrimEnd + WriteLine($"\" les_chaussettes_de_l'archiduchesse!!!!!!!!!!\".Trim() = \n{s8}"); + + //Split et Join + WriteLine("\n SPLIT ET JOIN"); + s8 = "Les chaussettes de l'archiduchesse"; + WriteLine($"\"{s8}\" est composé des mots suivants \n(\"Les chaussettes de l'archiduchesse\".Split()): "); + string[] mots = s8.Split(); + foreach (string m in mots) + { + WriteLine($"\t- {m}"); + } + WriteLine("On peut regrouper les mots précédents (tableau de string : string[] mots;) avec Join"); + string s9 = string.Join(" ", mots); + WriteLine($"string.Join(\" \", mots) = {s9}"); + + //Format + WriteLine("\n STRING.FORMAT"); + string format = "Il y a {0} élèves inscrits en {1} année à l'IUT pour l'année scolaire {2}"; + WriteLine("Le format : \"{0}\"", format); + string chaineFormatée = string.Format(format, 110, "2ème", "2011-2012"); + WriteLine("chaîne formatée avec le format : {0}", chaineFormatée); + WriteLine("on peut aussi tout faire dans le WriteLine, sans préciser string.Format : "); + WriteLine("Il y a {0} élèves inscrits en {1} année à l'IUT pour l'année scolaire {2}", 110, "2ème", "2010-2011"); + format = "Nb élèves : {0, -5} Année : {1, -5} Année universitaire : {2, 15}"; + WriteLine("format plus élaboré, pour imposer des tailles : \n{0}", format); + WriteLine("Quelques chaînes formatées (avec ou sans string.Format pour voir la différence d'écriture) : "); + chaineFormatée = string.Format(format, 110, "2ème", "2010-2011"); + WriteLine(chaineFormatée); + chaineFormatée = "Nb élèves : " + 110.ToString().PadRight(5) + " Année : " + "2ème".PadRight(5) + " Année universitaire : " + "2010-2011".PadLeft(15); + WriteLine(chaineFormatée); + chaineFormatée = "Nb élèves : " + 98.ToString().PadRight(5) + " Année : " + "2ème".PadRight(5) + " Année universitaire : " + "2010-2011".PadLeft(15); + WriteLine(chaineFormatée); + + //String Interpolation + WriteLine("\n STRING INTERPOLATION avec $"); + WriteLine($"Il y a {135} élèves inscrits en {"1ère"} année à l'IUT pour l'année scolaire {"2016 - 2017"}"); + + //comparaison de string + WriteLine("\n COMPARAISON DE STRING"); + //equality comparison + WriteLine($"\"yaha\" == \"YAHA\" ? " + ("yaha" == "YAHA")); + WriteLine($"\"yaha\".Equals(\"YAHA\") ? " + ("yaha".Equals("YAHA"))); + WriteLine($"string.Equals(\"yaha\", \"YAHA\") ? " + string.Equals("yaha", "YAHA")); + WriteLine($"\"yaha\".Equals(\"YAHA\", StringComparison.CurrentCultureIgnoreCase) ? " + ("yaha".Equals("YAHA", StringComparison.CurrentCultureIgnoreCase))); + WriteLine($"string.Equals(\"yaha\", \"YAHA\", StringComparison.CurrentCultureIgnoreCase) ? " + string.Equals("yaha", "YAHA", StringComparison.CurrentCultureIgnoreCase)); + + WriteLine($"string.Equals(\"éèàô\", \"eeao\") ? " + string.Compare("éèàô", "eeao", StringComparison.CurrentCultureIgnoreCase)); + + } + } +} diff --git a/p02_Fondamentaux/ex_006_001_string/ex_006_001_string.csproj b/p02_Fondamentaux/ex_006_001_string/ex_006_001_string.csproj new file mode 100644 index 0000000..530f4dd --- /dev/null +++ b/p02_Fondamentaux/ex_006_001_string/ex_006_001_string.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_006.0.6_string + Exe + ex_006.0.6_string + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_006_002_StringBuilder/Program.cs b/p02_Fondamentaux/ex_006_002_StringBuilder/Program.cs new file mode 100644 index 0000000..78d8449 --- /dev/null +++ b/p02_Fondamentaux/ex_006_002_StringBuilder/Program.cs @@ -0,0 +1,75 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-22 +// +// ======================================================================== + +using System; +using System.Text; +using static System.Console; + +namespace ex_006_002_StringBuilder +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + WindowWidth += 15; + WindowHeight = LargestWindowHeight; + + Write("STRING BUILDER : version "); + BackgroundColor = ConsoleColor.DarkBlue; + ForegroundColor = ConsoleColor.Yellow; + Write("mutable"); + ResetColor(); + WriteLine(" de string"); + + //construction + WriteLine("\n CONSTRUCTION"); + WriteLine("à l'aide d'un string : StringBuilder s1 = new StringBuilder(\"Bonjour\");"); + StringBuilder s1 = new StringBuilder("Bonjour"); + WriteLine(s1.ToString()); + WriteLine("à l'aide d'une sous-chaîne d'un string : s1 = new StringBuilder(\"Bonjour\", 0, 3, 3);"); + s1 = new StringBuilder("Bonjour", 0, 3, 3); + WriteLine(s1); + + //manipuler les string builder + WriteLine("\n MANIPULER LES STRING BUILDER"); + //append + WriteLine("APPEND"); + StringBuilder s7 = new StringBuilder().Append("Jim").Append(" ").Append("Raynor"); + WriteLine($"new StringBuilder().Append(\"Jim\").Append(\" \").Append(\"Raynor\"); contient {s7}"); + WriteLine("APPEND FORMAT"); + string format = "Il y a {0} élèves inscrits en {1} année à l'IUT pour l'année scolaire {2}"; + WriteLine("Le format : {0}", format); + StringBuilder s9 = new StringBuilder().AppendFormat(format, 110, "2ème", "2011-2012"); + WriteLine("new StringBuilder().AppendFormat(format, 110, \"2ème\", \"2011-2012\"); vaut :\n{0}", s9); + WriteLine(); + + //insert, remove, replace + StringBuilder s8 = new StringBuilder("Jim Raynor"); + WriteLine("StringBuilder s8 = new StringBuilder(\"Jim Raynor\");"); + WriteLine("REMOVE"); + s8.Remove(2, 3); + WriteLine("s8.Remove(2, 3) vaut {0}", s8); + WriteLine("INSERT"); + s8.Insert(2, "m R"); + WriteLine("s8.Insert(2, \"m R\") vaut {0}", s8); + WriteLine("CLEAR"); + s8.Clear(); + WriteLine("s8.Clear()"); + WriteLine("REPLACE"); + WriteLine("s8.Append(\"Les chaussettes de l'archiduchesse\");"); + s8.Append("Les chaussettes de l'archiduchesse"); + s8.Replace(" ", "_"); + WriteLine("s8.Replace(\" \", \"_\") vaut {0}", s8); + } + } +} diff --git a/p02_Fondamentaux/ex_006_002_StringBuilder/ex_006_002_StringBuilder.csproj b/p02_Fondamentaux/ex_006_002_StringBuilder/ex_006_002_StringBuilder.csproj new file mode 100644 index 0000000..d035e42 --- /dev/null +++ b/p02_Fondamentaux/ex_006_002_StringBuilder/ex_006_002_StringBuilder.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_006_002_StringBuilder + Exe + ex_006_002_StringBuilder + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_007_001_enum/Program.cs b/p02_Fondamentaux/ex_007_001_enum/Program.cs new file mode 100644 index 0000000..912a0ba --- /dev/null +++ b/p02_Fondamentaux/ex_007_001_enum/Program.cs @@ -0,0 +1,108 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; +namespace ex_007_001_enum +{ + class Program + { + /// + /// voici une énumération. + /// public n'est pas obligatoire. S'il est indiqué, l'énumération est utilisable en dehors de la classe. + /// + [Flags]//pas obligatoire mais conseillé pour améliorer le ToString de l'enum dans le cas des combinaisons + public enum MusicType : byte + { + Classic = 1, //00000001 + Jazz = 2, //00000010 + Pop = 4, //00000100 + Rock = 8, //00001000 + //on peut rajouter des combinaisons d'enum : ici, PopRock est à la fois Pop et Rock + //il faut pour cela que toutes les valeurs d'enum puissent s'exclure mutuellement + PopRock = Pop | Rock //00001100 + } + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //déclaration d'une variable de type MusicType + MusicType mMuzik; + //affectation d'une valeur possible à cette variable + mMuzik = MusicType.Jazz; + WriteLine(mMuzik); + + //un exemple d'utilisation + Write("la variable mMuzik est de type : "); + switch (mMuzik) + { + case MusicType.Classic: + WriteLine("Classique"); break; + case MusicType.Jazz: + WriteLine("Jazz"); break; + case MusicType.Pop: + WriteLine("Pop"); break; + case MusicType.Rock: + WriteLine("Rock"); break; + } + WriteLine(); + + //un enum peut être considéré comme un instance de la classe Enum + //exemple d'utilisation + WriteLine("liste des valeurs de l'énumération"); + foreach (string s in Enum.GetNames(typeof(MusicType))) + WriteLine(s); + WriteLine(); + + //autre utilisation + Write("la variable mMuzik est de type : "); + switch (mMuzik) + { + case MusicType.Classic: + WriteLine(MusicType.Classic.ToString()); break; + case MusicType.Jazz: + WriteLine(MusicType.Jazz.ToString()); break; + case MusicType.Pop: + WriteLine(MusicType.Pop.ToString()); break; + case MusicType.Rock: + WriteLine(MusicType.Rock.ToString()); break; + } + WriteLine(); + + //combinaison + mMuzik = MusicType.Jazz | MusicType.Rock; // 00001010 + WriteLine(mMuzik); //si vous utilisez [Flags], affiche "Jazz, Rock", sinon, affiche "10" + //on veut vérifier que mMuzik est du Jazz : + if ((mMuzik & MusicType.Jazz) != 0) //mMuzik & Jazz = 00001010 & 00000010 = 00000010 != 0 c'est donc du jazz (entre autres) + { + WriteLine("Includes Jazz"); + } + //on veut vérifier que mMuzik n'est pas de la Pop : + if ((mMuzik & MusicType.Pop) == 0) //mMuzik & Pop = 00001010 & 00000100 = 00000000 == 0 ce n'est donc pas de la Pop + { + WriteLine("pas pop"); + } + //finalement on veut rajouter Pop + mMuzik |= MusicType.Pop; //00001010 | 00000100 = 00001110 + if ((mMuzik & MusicType.Pop) != 0) //mMuzik & Pop = 00001110 & 00000100 = 00000100 != 0 c'est donc de la Pop + { + WriteLine("pop"); + } + //et enlever Jazz + mMuzik ^= MusicType.Jazz; //00001110 ^ 00000010 = 00001100 + if ((mMuzik & MusicType.Jazz) == 0) //mMuzik & Jazz = 00001100 & 00000010 = 00000000 == 0 ce n'est donc plus du jazz + { + WriteLine("pas jazz"); + } + } + } +} diff --git a/p02_Fondamentaux/ex_007_001_enum/ex_007_001_enum.csproj b/p02_Fondamentaux/ex_007_001_enum/ex_007_001_enum.csproj new file mode 100644 index 0000000..77cc9e8 --- /dev/null +++ b/p02_Fondamentaux/ex_007_001_enum/ex_007_001_enum.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_007_001_enum + Exe + ex_007_001_enum + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_008_001_if_else/Program.cs b/p02_Fondamentaux/ex_008_001_if_else/Program.cs new file mode 100644 index 0000000..50783a5 --- /dev/null +++ b/p02_Fondamentaux/ex_008_001_if_else/Program.cs @@ -0,0 +1,78 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_008_001_if_else +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + int vitesseMax = 70; + WriteLine($"La vitesse maximum autorisée est de {vitesseMax} km/h"); + Random random = new Random(); + int vitesse = random.Next(50, 150); + WriteLine($"Vous roulez à {vitesse} km/h"); + + if (vitesse <= vitesseMax) + { + WriteLine("Vous ne dépassez pas la vitesse maximum"); + } + else + { + WriteLine("Vous dépassez la vitesse maximum autorisée"); + if (vitesse < vitesseMax + 20) + { + WriteLine("L'amende forfaitaire s'élève à 68 euros"); + WriteLine("1 point est retiré du permis de conduire"); + } + else if (vitesse < vitesseMax + 50) + { + WriteLine("L'amende forfaitaire s'élève à 135 euros"); + if (vitesse < vitesseMax + 30) + { + WriteLine("2 points sont retirés du permis de conduire"); + } + else if (vitesse < vitesseMax + 40) + { + WriteLine("3 points sont retirés du permis de conduire"); + } + else if (vitesse < vitesseMax + 50) + { + WriteLine("4 points sont retirés du permis de conduire"); + + } + } + else + { + WriteLine("L'amende fofaitaire s'élève à 1500 euros"); + WriteLine("6 points sont retirés du permis de conduire"); + } + if (vitesse >= vitesseMax + 30) + { + WriteLine("Jusqu'à 3 ans de suspension de permis de conduire"); + if (vitesse >= vitesseMax + 40) + { + if (vitesse >= vitesseMax + 50) + { + WriteLine("Obligation d'accomplir, à ses frais, un stage de sensibilisation à la sécurité routière, confiscation du véhicule dont le prévenu s'est servi pour commettre l'infraction, s'il en est propriétaire."); + } + WriteLine("Une suspension immédiate du permis de conduire s'ajoute aux sanctions ci-dessus"); + } + } + } + } + } +} diff --git a/p02_Fondamentaux/ex_008_001_if_else/ex_008_001_if_else.csproj b/p02_Fondamentaux/ex_008_001_if_else/ex_008_001_if_else.csproj new file mode 100644 index 0000000..d22c0e1 --- /dev/null +++ b/p02_Fondamentaux/ex_008_001_if_else/ex_008_001_if_else.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_008_001_if_else + Exe + ex_008_001_if_else + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_008_002_switch/Program.cs b/p02_Fondamentaux/ex_008_002_switch/Program.cs new file mode 100644 index 0000000..4f7a34f --- /dev/null +++ b/p02_Fondamentaux/ex_008_002_switch/Program.cs @@ -0,0 +1,77 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_008_002_switch +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Random random = new Random(); + int i = random.Next(6); + + switch (i) + { + case 0: + WriteLine("i vaut 0"); //1 ou plusieurs instruction puis break; ("obligatoire") + break; + case 1: + case 2: + WriteLine("i vaut 1 ou 2"); // pour que deux case partagent les mêmes instructions, + break; // il faut que le premier soit vide et sans break; + case 3: + WriteLine("goto à la place de break"); //si le case n'est pas vide, je peux quand même rejoindre un autre case, + goto case 4; // à l'aide d'un goto + case 4: + WriteLine("i vaut 3 ou 4"); + break; + default: + WriteLine("i vaut autre chose"); + break; + } + + string[] jours = { "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche" }; + + string jour = jours[random.Next(jours.Length)]; + + //le switch fonctionne pour les chaînes de caractères !!! + switch (jour) + { + case "lundi": + WriteLine($"J'aime pas le {jour}"); + break; + case "mardi": + WriteLine($"Faut travailler un peu... le {jour}"); + break; + case "mercredi": + WriteLine("Ah l'époque où on ne travaillait pas le mercredi !"); + break; + case "jeudi": + case "vendredi": + goto case "mardi"; + case "samedi": + WriteLine("Vivement le weekend"); + break; + case "dimanche": + WriteLine("Je travaillerai demain"); + break; + default: + WriteLine("Quel jour on est !!!!????"); + break; + } + } + } +} diff --git a/p02_Fondamentaux/ex_008_002_switch/ex_008_002_switch.csproj b/p02_Fondamentaux/ex_008_002_switch/ex_008_002_switch.csproj new file mode 100644 index 0000000..d4177f8 --- /dev/null +++ b/p02_Fondamentaux/ex_008_002_switch/ex_008_002_switch.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_008_002_switch + Exe + ex_008_002_switch + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_008_003_ternary_operator/Program.cs b/p02_Fondamentaux/ex_008_003_ternary_operator/Program.cs new file mode 100644 index 0000000..929752a --- /dev/null +++ b/p02_Fondamentaux/ex_008_003_ternary_operator/Program.cs @@ -0,0 +1,37 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// Mise à jour : 2017-09-18 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_008_003_ternary_operator +{ + public class Program + { + public static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //L'opérateur conditionnel (conditional operator), aussi appelé opérateur ternaire (ternary operator), + //est le seul opérateur à prendre trois opérandes. + //Il a la forme suivante : c ? a : b + //où c est la condition, + // a est la valeur de retour si c est true + // b est la valeur de retour si c est false + + WriteLine("Rentrez quelque chose, je vous dirai si c'est un nombre ou non :"); + string chaine = ReadLine(); + bool condition = float.TryParse(chaine, out var nombre); + WriteLine(condition ? $"j'ai reconnu le nombre : {nombre.ToString()}" : "ce que vous avez entré n'est pas un nombre"); + } + } +} diff --git a/p02_Fondamentaux/ex_008_003_ternary_operator/ex_008_003_ternary_operator.csproj b/p02_Fondamentaux/ex_008_003_ternary_operator/ex_008_003_ternary_operator.csproj new file mode 100644 index 0000000..6a6363c --- /dev/null +++ b/p02_Fondamentaux/ex_008_003_ternary_operator/ex_008_003_ternary_operator.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_008_003_ternary_operator + Exe + ex_008_003_ternary_operator + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_008_004_null_operators/Program.cs b/p02_Fondamentaux/ex_008_004_null_operators/Program.cs new file mode 100644 index 0000000..bcf3d95 --- /dev/null +++ b/p02_Fondamentaux/ex_008_004_null_operators/Program.cs @@ -0,0 +1,74 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_008_004_null_operators +{ + public class Program + { + public static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //C# fournit deux opérateurs pour simplifier le travail avec les nulls + + //Null-coalescing operator : ?? + //"si l'opérande n'est pas nulle, rends-la moi ; sinon, donne-moi la valeur par défaut que je t'ai renseignée" + WriteLine("NULL-COLAESCING OPERATOR \n"); + WriteLine("s est une chaîne de caractères nulle"); + WriteLine("J'affiche s ?? \"rien\", c'est-à-dire que si s est null, on affichera la valeur par défaut : rien, sinon on affichera la valeur de s"); + string s = null; + string result = s ?? "rien"; + WriteLine($"-> {result}"); + + WriteLine(); + WriteLine("rentrez du texte, que je stockerai dans s :"); + s = ReadLine(); + WriteLine("J'affiche s ?? \"rien\", c'est-à-dire que si s est null, on affichera la valeur par défaut : rien, sinon on affichera la valeur de s"); + result = s ?? "rien"; + WriteLine($"-> {result}"); + WriteLine(); + + //Elvis Operator ou Null-conditional operator : ?. + //avec cet opérateur, pas besoin de tester si l'opérande est nulle avant d'appeler une méthode ou une propriété : + // si elle n'est pas nulle, fonctionne comme le . + // si elle est nulle, renvoie null (sans lancer l'exception NullReferenceException) + + WriteLine("Elvis operator ou Null-Conditional operator \n"); + WriteLine("s2 est une chaîne de caractères nulle"); + WriteLine("Je veux stocker s2.ToUpper() dans s3, mais puisque s2 est nulle, ça lance une exception :"); + string s2 = null; + string s3 = null; + try + { + s3 = s2.ToUpper(); + WriteLine(s3 != null ? s3 : "null"); + } + catch(NullReferenceException exception) + { + WriteLine(exception); + } + WriteLine(); + + WriteLine("Maintenant je veux stocker s2?.ToUpper() dans s3. Puisque s2 est nulle, null est stocké dans s3 mais sans lancer d'exception."); + s3 = s2?.ToUpper(); + WriteLine(s3 != null ? s3 : "null"); + WriteLine(); + WriteLine("\nmême chose avec le texte que vous allez rentrer :"); + s2 = ReadLine(); + s3 = s2?.ToUpper(); + WriteLine(s3 != null ? s3 : "null"); + + } + } +} diff --git a/p02_Fondamentaux/ex_008_004_null_operators/ex_008_004_null_operators.csproj b/p02_Fondamentaux/ex_008_004_null_operators/ex_008_004_null_operators.csproj new file mode 100644 index 0000000..82c3e65 --- /dev/null +++ b/p02_Fondamentaux/ex_008_004_null_operators/ex_008_004_null_operators.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_008_004_null_operators + Exe + ex_008_004_null_operators + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_008_005_pattern_matching/Program.cs b/p02_Fondamentaux/ex_008_005_pattern_matching/Program.cs new file mode 100644 index 0000000..0be36fe --- /dev/null +++ b/p02_Fondamentaux/ex_008_005_pattern_matching/Program.cs @@ -0,0 +1,149 @@ +// ======================================================================== +// +// Copyright (C) 2017-2018 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2017-09-19 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_008_005_pattern_matching +{ + class Program + { + static void Main(string[] args) + { + //C# 7.0 introduit le pattern matching, dont l'objectif est de permettre de "tester" si un objet respecte certaines conditions de "forme". + //En C# 7.0, on trouve pour le moment trois types de patterns : + // - constant patterns : qui permettent de tester si un objet est égal à une constante + // - type patterns : qui permettent de tester si un objet est de type T, et si c'est le cas, de le tester dans une nouvelle variable + // - var patterns : qui permettent de pacer un objet dans une nouvelle variable du même type + //Les patterns matching devraient certainement être beaucoup plus utilisés dans les versions futures de C#. + //Pour le moment, on en trouve deux cas d'utilisation majeurs : les expressions "is" et les clauses "case" dans les switch. + + //PATTERN MATCHING AND IS-EXPRESSIONS + void DisplayPrice(object price) + { + //constant pattern dans une is-expression avec comparaison à null + if (price is null) + { + WriteLine("Vous avez rentré une valeur nulle"); + return; + } + + //var pattern dans une is-expression + if (price is var price2) + { + WriteLine($"price2 est de type : {price2.GetType().Name} ; price2 a pour valeur : {price2}"); + } + + //type pattern dans une is-expression avec comparaison à un type numérique + if (!(price is float p)) + { + WriteLine($"price n'est pas du bon type. Type attendu : Single, Type utilisé : {price.GetType().Name}"); + return; + } + WriteLine($"Vous avez rentré : {p:0.00} euros"); + } + + DisplayPrice(null); + DisplayPrice(32.0f); + DisplayPrice("coucou"); + DisplayPrice(3); + + //var-pattern : on a une copie des variables, donc attention aux types références ! + void TestVarPattern(Nounours original) + { + WriteLine("Avant var pattern:"); + WriteLine($"original : {original}"); + if (original is var copie) + { + copie.Nom = "Chucky"; + copie.NbPoils = 4; + } + + WriteLine("Après var pattern:"); + WriteLine($"original : {original}"); + WriteLine($"copie : {copie}"); + } + + TestVarPattern(new Nounours { Nom = "Gizmo", NbPoils = 123456789, Naissance = new DateTime(1984, 6, 8) }); + + + + //PATTERN MATCHING DANS UN SWITCH AVEC DES CASES ET DES CONDITIONS SUPPLEMENTAIRES + + Nounours[] nounours = + { + new Nounours { Nom = "Gizmo", NbPoils = 123456789, Naissance = new DateTime(1984, 6, 8) }, + new NounoursProf { Nom = "Yoda", NbPoils = 4, Naissance = new DateTime(1980, 5, 21), Matière="How to become a Jedi?" }, + new NounoursElève { Nom = "Ewok", NbPoils = 98989898, Naissance = new DateTime(1983, 5, 25), FormationSuivie="How to destroy an AT-ST?" }, + new NounoursElève { Nom = "Chucky", NbPoils = 2, Naissance = new DateTime(1988, 11, 9), FormationSuivie="How to become naughty?" }, + null + }; + + void TestPatternMatchingInASwitch(Nounours monNounours) + { + //Il est possible de faire un switch sur n'importe quel type désormais + //La nouvelle gestion du switch fait que maintenant, l'ordre des clauses "case" a de l'importance (dans l'exemple ci-dessous, si on mettait la 2ème avant la 1ère, + //la 1ère ne serait jamais exécutée). Heureusement, le compilateur vous aidera a trouvé les cas qui ne seront jamais exécutés ! + switch (monNounours) + { + //type pattern avec une condition (when) + case NounoursElève élève when (élève.Naissance < new DateTime(1985, 1, 1)): + WriteLine($"{élève.Nom} est un vieil élève apprenant : {élève.FormationSuivie}"); + break; + //type pattern sans condition + case NounoursElève élève: + WriteLine($"{élève.Nom} est un élève apprenant : {élève.FormationSuivie}"); + break; + //type pattern + case NounoursProf prof: + WriteLine($"{prof.Nom} est un prof qui enseigne : {prof.Matière}"); + break; + //même s'il y a un autre case plus bas (comme dans cet exemple), le default est toujours évalué en dernier, pour des raisons de compatibilité. + //Pour une meilleure lisibilité, ne faites donc pas comme dans cet exemple : laissez le default à la fin + default: + WriteLine($"{monNounours.Nom} est un Nounours comme un autre, sans histoire particulière..."); + break; + //constant pattern + case null: + WriteLine($"Attention, ce Nounours est null ! (nom du paramètre : {nameof(monNounours)})"); + break; + } + } + + foreach (var n in nounours) + { + TestPatternMatchingInASwitch(n); + } + } + } + + class Nounours + { + public string Nom { get; set; } + public int NbPoils { get; set; } + public DateTime Naissance { get; set; } + + public override string ToString() + { + return $"{Nom} a {NbPoils} poils et est né en {Naissance.Year}"; + } + } + + class NounoursProf : Nounours + { + public string Matière { get; set; } + } + + class NounoursElève : Nounours + { + public string FormationSuivie { get; set; } + } +} diff --git a/p02_Fondamentaux/ex_008_005_pattern_matching/ex_008_005_pattern_matching.csproj b/p02_Fondamentaux/ex_008_005_pattern_matching/ex_008_005_pattern_matching.csproj new file mode 100644 index 0000000..a69c6ed --- /dev/null +++ b/p02_Fondamentaux/ex_008_005_pattern_matching/ex_008_005_pattern_matching.csproj @@ -0,0 +1,6 @@ + + + Exe + net6.0 + + diff --git a/p02_Fondamentaux/ex_009_001_bouclesIteratives/Program.cs b/p02_Fondamentaux/ex_009_001_bouclesIteratives/Program.cs new file mode 100644 index 0000000..02cc061 --- /dev/null +++ b/p02_Fondamentaux/ex_009_001_bouclesIteratives/Program.cs @@ -0,0 +1,74 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_009_001_bouclesIteratives +{ + class Program + { + static void Main(string[] args) + { + string[] jours = { "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche" }; + + //BOUCLE WHILE + WriteLine("boucle while"); + int i = 0; + while (i < jours.Length) + { + Write($"{jours[i]} "); + i++; + } + + WriteLine(); + + //BOUCLE DO-WHILE + WriteLine("boucle do-while"); + int j = 0; + do + { + Write($"{jours[j]} "); + j++; + } + while (j < jours.Length); + + WriteLine(); + + //BOUCLE FOR + WriteLine("boucle for"); + for (int k = 0; k < jours.Length; k++) + { + Write($"{jours[k]} "); + } + + WriteLine(); + + //BOUCLE FOREACH + WriteLine("boucle foreach"); + foreach (string jour in jours) + { + Write($"{jour} "); + } + + WriteLine(); + + foreach (string jour in jours) + { + if (jour == "Mercredi") + continue; //continue est autorisé : passe directement à l'itération suivante + if (jour == "Samedi") + break; //break est autorisé : arrête la boucle + WriteLine(jour); + } + } + } +} diff --git a/p02_Fondamentaux/ex_009_001_bouclesIteratives/ex_009_001_bouclesIteratives.csproj b/p02_Fondamentaux/ex_009_001_bouclesIteratives/ex_009_001_bouclesIteratives.csproj new file mode 100644 index 0000000..d7a63db --- /dev/null +++ b/p02_Fondamentaux/ex_009_001_bouclesIteratives/ex_009_001_bouclesIteratives.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_009_001_bouclesIteratives + Exe + ex_009_001_bouclesIteratives + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_010_001_methodParametersAndModifiers/Program.cs b/p02_Fondamentaux/ex_010_001_methodParametersAndModifiers/Program.cs new file mode 100644 index 0000000..a7e6ab1 --- /dev/null +++ b/p02_Fondamentaux/ex_010_001_methodParametersAndModifiers/Program.cs @@ -0,0 +1,183 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// Mise à jour : 2017-09-28 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_010_001_methodParametersAndModifiers +{ + class ExFunct + { + //passage d'arguments par valeur + public int Somme(int a, int b) + { + int result = a + b; + //celui qui appelle cette méthode ne pourra pas voir ces changements + //car a et b sont ici des copies locales des paramètres qu'il a passés + a++; + b++; + return result; + } + + //passage d'argument par référence (notez le mot-clé ref) + public int SommeRef(ref int a, ref int b) + { + int result = a + b; + //celui qui appelle cette méthode verra les deux paramètres qu'il a passés + //modifiés par celle-ci, car ils sont passés par référence + a++; + b++; + return result; + } + + //passage de tableaux en argument (pas besoin de préciser ref, le tableau en est une) + public int SommeTab(int[] tab) + { + int result = 0; + for (int i = 0; i < tab.Length; i++) + { + //celui qui appelle cette méthode verra les valeurs du tableau passé en paramètre + //modifiées par la méthode, car un tableau est toujours passé par référence + //(un tableau EST un type REFERENCE) + result += tab[i]; + tab[i]++; + } + return result; + } + + //passage d'argument out : indique que la variable est initialisée par la fonction appelée (notez le mot-clé out) + public void SommeOut(int a, int b, out int result) + { + //celui qui appelle cette méthode peut donner result sans l'initialiser + //le mot-clé out garantit que ce paramètre sera initialisé dans la méthode + result = a + b; + } + + //passage d'arguments en nombre indéterminé, en dernier paramètre de la méthode uniquement + public int SommeParams(params int[] ints) + { + //l'utilisateur de la méthode n'a pas besoin de préciser params + //en revanche, il peut passer autant d'arguments de type int qu'il le souhaite. + //À l'intérieur de la méthode, ces arguments sont traités comme un tableau d'entiers, + //mais tous les éléments de ce tableau sont copiés par valeur. + int result = 0; + for (int i = 0; i < ints.Length; i++) + { + result += ints[i]; + ints[i]++; + } + return result; + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + ExFunct f = new ExFunct(); + int a = 2; + int b = 3; + WriteLine("f.Somme(a, b)"); + WriteLine($"a (avant) = {a}"); + WriteLine($"b (avant) = {b}"); + WriteLine($"résultat : {f.Somme(a, b)}"); //passage d'arguments par valeur + WriteLine($"a (après) = {a}"); + WriteLine($"b (après) = {b}"); + WriteLine(); + + WriteLine("f.SommeRef(ref a, ref b)"); + WriteLine($"a (avant) = {a}"); + WriteLine($"b (avant) = {b}"); + WriteLine($"résultat : {f.SommeRef(ref a, ref b)}");//passage d'argument par référence (notez le mot clé ref) --> a est modifié par la fonction + WriteLine($"a (après) = {a}"); + WriteLine($"b (après) = {b}"); + WriteLine(); + + WriteLine("tableaux"); + int[] t = { 1, 2, 3 }; + Write("tableau t (avant) : "); + foreach (int i in t) Write($"{i} "); + WriteLine(); + f.SommeTab(t); //passage de tableau en argument (pas besoin de ref, car c'est est une). + WriteLine("f.SommeTab(t);"); + Write("tableau t (après) : "); + foreach (int i in t) Write($"{i} "); + WriteLine(); + WriteLine(); + + int c; + WriteLine("f.SommeOut(a, b, out c);"); + WriteLine($"a (avant) = {a}"); + WriteLine($"b (avant) = {b}"); + WriteLine("c est non assigné"); + f.SommeOut(a, b, out c); + WriteLine($"résultat : {c}"); //passage d'argument out. c n'est pas initialisé, et on utilise le mot clé out + WriteLine($"a (après) = {a}"); + WriteLine($"b (après) = {b}"); + WriteLine($"c (après) = {c}"); + WriteLine(); + + //Dans l'exemple ci-dessus de l'utilisation des paramètres out, il est nécessaire de déclarer c avant son utilisation : + //int c; + //f.SommeOut(a, b, out c); + //Depuis C# 7.0, l'utilisation a été simplifiée : vous pouvez maintenant déclarer la variable lors de son utilisation : + //f.SommeOut(a, b, out int c2); + //La portée de la variable est alors le bloc contenant l'instruction prenant le paramètre out en paramètre. + + WriteLine("f.SommeOut(a, b, out int c2);"); + WriteLine($"a (avant) = {a}"); + WriteLine($"b (avant) = {b}"); + WriteLine("c2 est non assigné et déclaré lors de l'appel de la méthode SommeOut"); + f.SommeOut(a, b, out int c2); + WriteLine($"résultat : {c2}"); //passage d'argument out. c2 n'est pas initialisé, et on utilise le mot clé out + WriteLine($"a (après) = {a}"); + WriteLine($"b (après) = {b}"); + WriteLine($"c2 (après) = {c2}"); + WriteLine(); + + //Il est également possible d'utiliser var, tant qu'il n'y a pas de conflit (surcharge de méthodes), ce qui rend l'utilisation encore plus simple + WriteLine("f.SommeOut(a, b, out var c3);"); + WriteLine($"a (avant) = {a}"); + WriteLine($"b (avant) = {b}"); + WriteLine("c3 est non assigné et déclaré lors de l'appel de la méthode SommeOut"); + f.SommeOut(a, b, out var c3); + WriteLine($"résultat : {c3}"); //passage d'argument out. c3 n'est pas initialisé, et on utilise le mot clé out + WriteLine($"a (après) = {a}"); + WriteLine($"b (après) = {b}"); + WriteLine($"c3 (après) = {c3}"); + WriteLine(); + + //Enfin, il est également possible de préciser qu'on veut ignorer une variable out avec _ (discard variables) + WriteLine("f.SommeOut(a, b, out _);"); + WriteLine($"a (avant) = {a}"); + WriteLine($"b (avant) = {b}"); + WriteLine("on ne souhaite pas récupérer le paramètre en out"); + f.SommeOut(a, b, out _); + WriteLine($"a (après) = {a}"); + WriteLine($"b (après) = {b}"); + WriteLine(); + + WriteLine("f.SommeParams(a, b, c)"); + WriteLine($"a (avant) = {a}"); + WriteLine($"b (avant) = {b}"); + WriteLine($"c (avant) = {c}"); + //passage d'arguments en nombre indéterminé + WriteLine($"résultat : {f.SommeParams(a, b, c)}"); + WriteLine($"a (après) = {a}"); + WriteLine($"b (après) = {b}"); + WriteLine($"c (après) = {c}"); + WriteLine(); + } + } +} diff --git a/p02_Fondamentaux/ex_010_001_methodParametersAndModifiers/ex_010_001_methodParametersAndModifiers.csproj b/p02_Fondamentaux/ex_010_001_methodParametersAndModifiers/ex_010_001_methodParametersAndModifiers.csproj new file mode 100644 index 0000000..ad8afb4 --- /dev/null +++ b/p02_Fondamentaux/ex_010_001_methodParametersAndModifiers/ex_010_001_methodParametersAndModifiers.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_010_001_methodParametersAndModifiers + Exe + ex_010_001_methodParametersAndModifiers + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_010_002_optionalParameters/Program.cs b/p02_Fondamentaux/ex_010_002_optionalParameters/Program.cs new file mode 100644 index 0000000..658700c --- /dev/null +++ b/p02_Fondamentaux/ex_010_002_optionalParameters/Program.cs @@ -0,0 +1,45 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_010_002_optionalParameters +{ + class ExFunct + { + //arguments optionnels (et arguments nommés) + public string SomeString(int x = 1, int y = 2, int z = 3) + { + return string.Format($"x : {x}, y : {y}, z : {z}"); + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + ExFunct f = new ExFunct(); + + WriteLine("arguments optionnels et arguments nommés"); + WriteLine($"SomeString() : {f.SomeString()}"); + WriteLine($"SomeString(4) : {f.SomeString(4)}"); + WriteLine($"SomeString(4, 5) : {f.SomeString(4, 5)}"); + WriteLine($"SomeString(4, 5, 6) : {f.SomeString(4, 5, 6)}"); + WriteLine($"SomeString(y:5, z:6) : {f.SomeString(y: 5, z: 6)}"); + WriteLine($"SomeString(y:5) : {f.SomeString(y: 5)}"); + //WriteLine($"SomeString(y:5, 6) : {f.SomeString(y:5, 6)}"); + //ne compile pas (pas d'arguments positionnels après un argument nommé) + } + } +} diff --git a/p02_Fondamentaux/ex_010_002_optionalParameters/ex_010_002_optionalParameters.csproj b/p02_Fondamentaux/ex_010_002_optionalParameters/ex_010_002_optionalParameters.csproj new file mode 100644 index 0000000..1e0f543 --- /dev/null +++ b/p02_Fondamentaux/ex_010_002_optionalParameters/ex_010_002_optionalParameters.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_010_002_optionalParameters + Exe + ex_010_002_optionalParameters + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_010_003_interets_des_optionalparameters/Program.cs b/p02_Fondamentaux/ex_010_003_interets_des_optionalparameters/Program.cs new file mode 100644 index 0000000..94b36d8 --- /dev/null +++ b/p02_Fondamentaux/ex_010_003_interets_des_optionalparameters/Program.cs @@ -0,0 +1,122 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using static System.Console; + +//cet exemple montre trois manières différentes de gérer les paramètres par défaut +namespace ex_010_003_interets_des_optionalparameters +{ + class C1 + { + /// + /// une méthode qui gère les paramètres remplis avec null : + /// l'utilisateur doit toujours renseigner chaque paramètre + /// + /// + /// + /// + /// + public static string Method(string s1, string s2, string s3) + { + if (s1 == null) + { + s1 = "nothing"; + } + if (s2 == null) + { + s2 = "nothing"; + } + if (s3 == null) + { + s3 = "nothing"; + } + return string.Format($"{s1} + {s2} + {s3}"); + } + } + + class C2 + { + /// + /// la méthode Method possède trois overload afin de gérer des valeurs par défaut + /// Risque de confusion et impossibilité de faire toutes les combinaisons. + /// + /// + /// + /// + /// + public static string Method(string s1, string s2, string s3) + { + return string.Format($"{s1} + {s2} + {s3}"); + } + public static string Method(string s1, string s2) + { + return string.Format($"{s1} + {s2} + nothing"); + } + public static string Method(string s) + { + return string.Format($"{s} + nothing + nothing"); + } + } + + class C3 + { + /// + /// avec les paramètres optionnels, toutes les combinaisons sont possibles et une seule méthode suffit. + /// Un seul inconvénient : les noms des paramètres font maintenant partis de l'API + /// + /// + /// + /// + /// + public static string Method(string s1 = "nothing", string s2 = "nothing", string s3 = "nothing") + { + return string.Format($"{s1} + {s2} + {s3}"); + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + WriteLine("Méthode 1 : tous les champs doivent toujours être renseignés"); + WriteLine("C1.Method(\"a\", \"b\", \"c\")"); + WriteLine(C1.Method("a", "b", "c")); + WriteLine("C1.Method(\"a\", \"b\", null)"); + WriteLine(C1.Method("a", "b", null)); + WriteLine("C1.Method(\"a\", null, null)"); + WriteLine(C1.Method("a", null, null)); + WriteLine("C1.Method(null, \"b\", null)"); + WriteLine(C1.Method(null, "b", null)); + + WriteLine(); + WriteLine("Méthode 2 : Overloads"); + WriteLine("C2.Method(\"a\", \"b\", \"c\")"); + WriteLine(C2.Method("a", "b", "c")); + WriteLine("C2.Method(\"a\", \"b\")"); + WriteLine(C2.Method("a", "b")); + WriteLine("C2.Method(\"a\")"); + WriteLine(C2.Method("a")); + + WriteLine(); + WriteLine("Méthode 3 : optional parameters and named parameters"); + WriteLine("C3.Method(\"a\", \"b\", \"c\")"); + WriteLine(C3.Method("a", "b", "c")); + WriteLine("C3.Method(\"a\", \"b\")"); + WriteLine(C3.Method("a", "b")); + WriteLine("C3.Method(\"a\")"); + WriteLine(C3.Method("a")); + WriteLine("C3.Method(s2:\"b\")"); + WriteLine(C3.Method(s2: "b")); + } + } +} diff --git a/p02_Fondamentaux/ex_010_003_interets_des_optionalparameters/ex_010_003_interets_des_optionalparameters.csproj b/p02_Fondamentaux/ex_010_003_interets_des_optionalparameters/ex_010_003_interets_des_optionalparameters.csproj new file mode 100644 index 0000000..406a092 --- /dev/null +++ b/p02_Fondamentaux/ex_010_003_interets_des_optionalparameters/ex_010_003_interets_des_optionalparameters.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_010_003_interets_des_optionalparameters + Exe + ex_010_003_interets_des_optionalparameters + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_012_001_nullableTypes/Program.cs b/p02_Fondamentaux/ex_012_001_nullableTypes/Program.cs new file mode 100644 index 0000000..521e640 --- /dev/null +++ b/p02_Fondamentaux/ex_012_001_nullableTypes/Program.cs @@ -0,0 +1,51 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_012_001_nullableTypes +{ + class Program + { + //les types référence peuvent représenter une valeur non-existante (null reference) + //par contre, les valeurs elles, ne le peuvent pas : int i = null n'est pas autorisé + //En C# on peut quand même le faire, à l'aide des nullable types + static void Main(string[] args) + { + int? i = null; + WriteLine("int? i = null"); + Write("i == null ? "); + WriteLine(i == null); + WriteLine($"i.HasValue {i.HasValue}"); + WriteLine($"i or default : {i.GetValueOrDefault()}"); + i = 2; + WriteLine("i = 2"); + Write("i == null ? "); + WriteLine(i == null); + WriteLine($"i.HasValue {i.HasValue}"); + WriteLine($"i or default : {i.GetValueOrDefault()}"); + WriteLine($"i.Value : {i.Value}"); + + //l'opérateur ?? est le null coalescing operator + int? x = null; + int y = x ?? 5; // y vaut 5 car x est null + int? a = 1; + int? b = 2; + int? z = x ?? a ?? b; // y vaut 1 car a est la première valeur non nulle + int? c = null; + int? w = x ?? c ?? b; // y vaut 2 car b est la première valeur non nulle + + + } + } +} + diff --git a/p02_Fondamentaux/ex_012_001_nullableTypes/ex_012_001_nullableTypes.csproj b/p02_Fondamentaux/ex_012_001_nullableTypes/ex_012_001_nullableTypes.csproj new file mode 100644 index 0000000..f29fd0a --- /dev/null +++ b/p02_Fondamentaux/ex_012_001_nullableTypes/ex_012_001_nullableTypes.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_012_001_nullableTypes + Exe + ex_012_001_nullableTypes + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_013_001_FormattingParsingNumEtBool/Program.cs b/p02_Fondamentaux/ex_013_001_FormattingParsingNumEtBool/Program.cs new file mode 100644 index 0000000..5006dbb --- /dev/null +++ b/p02_Fondamentaux/ex_013_001_FormattingParsingNumEtBool/Program.cs @@ -0,0 +1,174 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using System.Text; +using static System.Console; + +namespace ex_013_001_FormattingParsingTypesNumeriquesEtBool +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + //Formatage avec ToString + bool b = true; + string s = b.ToString(); + WriteLine($"b vaut {s}"); + + int i = 123, j = 1234, k = 12345; + s = i.ToString(); + WriteLine($"i vaut {i}"); + + WriteLine(); + + WriteLine("FORMATS STANDARDS"); + //il existe énormément de variantes : + //Format standards + float f = 12345.6789f; + float g = 0.00000006f; + float h = 123456789.123f; + WriteLine($"f = {f.ToString()}"); + WriteLine($"g = {g.ToString()}"); + WriteLine($"h = {h.ToString()}"); + WriteLine("\nG : notation exponentielle pour les grands ou les petits nombres"); + WriteLine($"f.ToString(\"G\") : {f.ToString("G")}"); + WriteLine($"g.ToString(\"G\") : {g.ToString("G")}"); + WriteLine($"h.ToString(\"G\") : {h.ToString("G")}"); + + WriteLine("\nG3 : limite la notation à 3 chiffres maximum"); + WriteLine($"f.ToString(\"G3\") : {f.ToString("G3")}"); + WriteLine($"g.ToString(\"G3\") : {g.ToString("G3")}"); + WriteLine($"h.ToString(\"G3\") : {h.ToString("G3")}"); + + WriteLine("\nF2 : arrondit à deux décimales"); + WriteLine($"f.ToString(\"F2\") : {f.ToString("F2")}"); + WriteLine($"g.ToString(\"F2\") : {g.ToString("F2")}"); + WriteLine($"h.ToString(\"F2\") : {h.ToString("F2")}"); + + WriteLine("\nE : force la notation exponentielle (avec 6 chiffres, existe aussi avec E2, E3..."); + WriteLine($"f.ToString(\"E\") : {f.ToString("E")}"); + WriteLine($"g.ToString(\"E2 \") : {g.ToString("E2")}"); + WriteLine($"h.ToString(\"E3\") : {h.ToString("E3")}"); + + WriteLine("\nC : currency (monnaie)"); + WriteLine($"f.ToString(\"C\") : {f.ToString("C")}"); + //number format info + System.Globalization.NumberFormatInfo monnaie = new System.Globalization.NumberFormatInfo(); + monnaie.CurrencySymbol = "$$"; + WriteLine($"g.ToString(\"C2 \") : {g.ToString("C2", monnaie)}"); + //culture info + System.Globalization.CultureInfo info = new System.Globalization.CultureInfo("en-GB"); + WriteLine($"h.ToString(\"C3\") : {h.ToString("C3", info)}"); + + WriteLine(); + + float p = 0.5349f, q = 0.53492f, r = 0.534923f; + WriteLine($"p = {p.ToString()}"); + WriteLine($"q = {q.ToString()}"); + WriteLine($"r = {r.ToString()}"); + WriteLine("\nP : pourcentage"); + WriteLine($"p.ToString(\"P\") : {p.ToString("P")}"); + WriteLine($"a.ToString(\"P0 \") : {q.ToString("P0")}"); + WriteLine($"r.ToString(\"P1\") : {r.ToString("P1")}"); + + WriteLine(); + + WriteLine($"i = {i.ToString()}"); + WriteLine($"j = {j.ToString()}"); + WriteLine($"k = {k.ToString()}"); + WriteLine("\nD4 : pad left avec des 0 à gauche pour avoir au moins 4 chiffres"); + WriteLine($"i.ToString(\"D4\") : {i.ToString("D4")}"); + WriteLine($"j.ToString(\"D4\") : {j.ToString("D4")}"); + WriteLine($"k.ToString(\"D4\") : {k.ToString("D4")}"); + + WriteLine(); + + //formats personnalisés + WriteLine("FORMATS PERSONNALISES"); + float l = 123.456f; + WriteLine($"l = {l}"); + WriteLine("\n .## limite à deux nombres max après la virgule"); + WriteLine($"l.ToString(\".##\") : {l.ToString(".##")}"); + WriteLine($"l.ToString(\".###\") : {l.ToString(".###")}"); + WriteLine("\n .00 comme précédemment mais complète avec des 00"); + WriteLine($"l.ToString(\".00\") : {l.ToString(".00")}"); + WriteLine($"l.ToString(\".0000\") : {l.ToString(".0000")}"); + WriteLine($"l.ToString(\"00.00\") : {l.ToString("00.00")}"); + WriteLine($"l.ToString(\"0000.00\") : {l.ToString("0000.00")}"); + + int m = 5, n = -5, o = 0; + WriteLine(); + WriteLine($"m = {m}"); + WriteLine($"n = {n}"); + WriteLine($"o = {o}"); + WriteLine("\n +#;(#);zero rend le nombre \"+lenombre\" si positif, \"(lenombre)\" si négatif, \"zero\" si = 0"); + WriteLine($"m.ToString(\"+#;(#);zero\") : {m.ToString("+#;(#);zero")}"); + WriteLine($"n.ToString(\"+#;(#);zero\") : {n.ToString("+#;(#);zero")}"); + WriteLine($"o.ToString(\"+#;(#);zero\") : {o.ToString("+#;(#);zero")}"); + + WriteLine(); + + //parsing + WriteLine("PARSING"); + + //méthodes statiques Parse, mais il vaut mieux la mettre dans un bloc try + WriteLine("i = int.Parse(\"yaha\");"); + try + { + i = int.Parse("yaha"); + } + catch (FormatException e) + { + WriteLine($"le parse a échoué (exception : {e.Message})"); + } + WriteLine("i = int.Parse(123);"); + + try + { + i = int.Parse("123"); + } + catch (FormatException e) + { + WriteLine($"le parse a échoué (exception : {e.Message})"); + } + WriteLine(i); + + //ou avec TryParse : rend true si a fonctionné et le résultat dans le paramètre out + //rend false si n'a pas fonctionné et il ne faut surtout pas regarder le résultat dans out + // pas d'exception de lancée + WriteLine("int.TryParse(\"yaha\", out i) + \" échec\""); + WriteLine($"{int.TryParse("yaha", out i)} échec"); + WriteLine("int.TryParse(\"123\", out i) + \" \" + i"); + WriteLine($"{int.TryParse("123", out i)} {i}"); + + //attention à la culture ! + //WriteLine(double.Parse("1.23")); + WriteLine("double.Parse(\"1,23\")"); + WriteLine(double.Parse("1,23")); + WriteLine("double.Parse(\"1.23\", System.Globalization.CultureInfo.InvariantCulture)"); + WriteLine(double.Parse("1.23", System.Globalization.CultureInfo.InvariantCulture)); + + //on peut compléter le parsing avec des styles (flags) + //autoriser les parenthèses : + string stringToParse = "(123)"; + WriteLine($"stringToParse = {stringToParse}"); + WriteLine($"int.TryParse(stringToParse, out i) = {int.TryParse(stringToParse, out i)}"); + WriteLine("int.TryParse(stringToParse, System.Globalization.NumberStyles.AllowParentheses, System.Globalization.CultureInfo.CurrentCulture, out i) = {0}\ni vaut = {1}", + int.TryParse(stringToParse, + System.Globalization.NumberStyles.AllowParentheses, + System.Globalization.CultureInfo.CurrentCulture, + out i), + i); + } + } +} diff --git a/p02_Fondamentaux/ex_013_001_FormattingParsingNumEtBool/ex_013_001_FormattingParsingNumEtBool.csproj b/p02_Fondamentaux/ex_013_001_FormattingParsingNumEtBool/ex_013_001_FormattingParsingNumEtBool.csproj new file mode 100644 index 0000000..956f3f4 --- /dev/null +++ b/p02_Fondamentaux/ex_013_001_FormattingParsingNumEtBool/ex_013_001_FormattingParsingNumEtBool.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_013_001_FormattingParsingNumEtBool + Exe + ex_013_001_FormattingParsingNumEtBool + 6.0.6 + false + false + false + + diff --git a/p02_Fondamentaux/ex_013_002_FormattingParsingDateTime/Program.cs b/p02_Fondamentaux/ex_013_002_FormattingParsingDateTime/Program.cs new file mode 100644 index 0000000..9e24e13 --- /dev/null +++ b/p02_Fondamentaux/ex_013_002_FormattingParsingDateTime/Program.cs @@ -0,0 +1,55 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_013_002_FormattingParsingDateTime +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //Formatages standards et sensible à la culture + DateTime maintenant = DateTime.Now; + + WriteLine(maintenant.ToString("d")); + WriteLine(maintenant.ToString("D")); + WriteLine(maintenant.ToString("t")); + WriteLine(maintenant.ToString("T")); + WriteLine(maintenant.ToString("f")); + WriteLine(maintenant.ToString("F")); + WriteLine(maintenant.ToString("g")); + WriteLine(maintenant.ToString("m")); + WriteLine(maintenant.ToString("y")); + + //Formatage standard et insensible à la culture + WriteLine(maintenant.ToString("o")); //conseillé lors de l'écriture dans un fichier (pour garantir la lecture) + + //Formatages personnalisés + WriteLine(maintenant.ToString("yyyy-MM-dd HH:mm:ss")); + WriteLine(maintenant.ToString("dd MMM yyyy HH:mm:ss")); + WriteLine(maintenant.ToString("ddd dd MMMM yyyy HH:mm:ss")); + WriteLine(maintenant.ToString("dddd dd MMMM yyyy HH:mm:ss")); + + //le troisième argument de ParseExact permet de préciser la culture. Si null, alors prend la culture par défaut sur votre .NET + string dateString = maintenant.ToString("o"); + DateTime dateParsée = DateTime.ParseExact(dateString, "o", null); + WriteLine(dateParsée); + + dateString = maintenant.ToString("dddd dd MMMM yyyy HH:mm:ss"); + dateParsée = DateTime.ParseExact(dateString, "dddd dd MMMM yyyy HH:mm:ss", null); + WriteLine(dateParsée); + } + } +} diff --git a/p02_Fondamentaux/ex_013_002_FormattingParsingDateTime/ex_013_002_FormattingParsingDateTime.csproj b/p02_Fondamentaux/ex_013_002_FormattingParsingDateTime/ex_013_002_FormattingParsingDateTime.csproj new file mode 100644 index 0000000..88545c5 --- /dev/null +++ b/p02_Fondamentaux/ex_013_002_FormattingParsingDateTime/ex_013_002_FormattingParsingDateTime.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_013_002_FormattingParsingDateTime + Exe + ex_013_002_FormattingParsingDateTime + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_014_001_namespace_et_nomDUneClasse/Program.cs b/p03_POO/ex_014_001_namespace_et_nomDUneClasse/Program.cs new file mode 100644 index 0000000..65eb844 --- /dev/null +++ b/p03_POO/ex_014_001_namespace_et_nomDUneClasse/Program.cs @@ -0,0 +1,63 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using static System.Console; + +// un namespace est un domaine dans lequel les types doivent être uniques +// on peut organiser les types de manière hiérarchique, pour deux raisons : +// - éviter les conflits +// - les rendre plus faciles à trouver +// par exemple : System.Collections.Generic.List<> + +//using permet d'importer un namespace et ses types (mais pas les namespaces qu'il contient) +using Ext; +using Ext.Milieu.Int; + + +namespace Ext.Milieu.Int +{ + public class C1 { } //le vrai nom de C1 est : Ext.Milieu.Int.C1 +} + +namespace Ext +{ + namespace Milieu + { + namespace Int + { + public class C2 { } // le vrai nom de C2 est : Ext.Milieu.Int.C2 + } + public class C3 { } //le vrai nom de C3 est : Ext.Milieu.C3 + } + public class C4 { } // le vrai nom de C4 est : Ext.C4 +} + +namespace ex_014_001_namespace_et_nomDUneClasse +{ + class Program + { + static void Main(string[] args) + { + C4 b = new C4(); + WriteLine(b.GetType()); + + C1 c = new C1(); + WriteLine(c.GetType()); + + C2 d = new C2(); + WriteLine(d.GetType()); + + Ext.Milieu.C3 a = new Ext.Milieu.C3(); + WriteLine(a.GetType()); + } + } +} + diff --git a/p03_POO/ex_014_001_namespace_et_nomDUneClasse/ex_014_001_namespace_et_nomDUneClasse.csproj b/p03_POO/ex_014_001_namespace_et_nomDUneClasse/ex_014_001_namespace_et_nomDUneClasse.csproj new file mode 100644 index 0000000..1c88f28 --- /dev/null +++ b/p03_POO/ex_014_001_namespace_et_nomDUneClasse/ex_014_001_namespace_et_nomDUneClasse.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_014_001_namespace_et_nomDUneClasse + Exe + ex_014_001_namespace_et_nomDUneClasse + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_014_002_typesImbriques/Program.cs b/p03_POO/ex_014_002_typesImbriques/Program.cs new file mode 100644 index 0000000..a784272 --- /dev/null +++ b/p03_POO/ex_014_002_typesImbriques/Program.cs @@ -0,0 +1,50 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +namespace ex_014_002_typesImbriques +{ + public class UneClasse + { + class UneClasseImbriquéePrivée + { + } + + private UneClasseImbriquéePrivée mMembre1; + + //public UneClasseImbriquéePrivée mMembre2; //on ne peut pas avoir de membre autre que public de ce type, car la classe imbriquée est privée + //elle n'est donc pas visible en dehors de la classe UneClasse + + + public class UneClasseImbriquéePublique + { + } + + private UneClasseImbriquéePublique mMembre3; + public UneClasseImbriquéePublique mMembre4; + + public enum UnEnumImbriqué + { + Inconnu, + Connu + } + } + + class Program + { + static void Main(string[] args) + { + UneClasse uneClasse = new UneClasse(); + var qqchse = uneClasse.mMembre4; + + UneClasse.UnEnumImbriqué variable = UneClasse.UnEnumImbriqué.Connu; + } + } +} diff --git a/p03_POO/ex_014_002_typesImbriques/ex_014_002_typesImbriques.csproj b/p03_POO/ex_014_002_typesImbriques/ex_014_002_typesImbriques.csproj new file mode 100644 index 0000000..e5ad701 --- /dev/null +++ b/p03_POO/ex_014_002_typesImbriques/ex_014_002_typesImbriques.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_014_002_typesImbriques + Exe + ex_014_002_typesImbriques + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_014_003_ClasseChampInitialiseurs/Program.cs b/p03_POO/ex_014_003_ClasseChampInitialiseurs/Program.cs new file mode 100644 index 0000000..1e6aa52 --- /dev/null +++ b/p03_POO/ex_014_003_ClasseChampInitialiseurs/Program.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +namespace ex_014_003_ClasseChampInitialiseurs +{ + //la classe est le type de référence le plus commun + //avant class, on trouve un ou plusieurs modifiers : public, internal, abstract, sealed, static, unsafe, partial + // public rend cette classe visible et utilisable dans d'autres assemblages + // internal rend cette classe visible et utilisable dans l'assemblage uniquement + // les autres seront vus plus tard + internal class Disque + { + //un champ est une variable qui est un membre de cette classe + //pour respecter le principe d'encapsulation, un champ devrait toujours être privé (modifieur [accesseur] private par défaut) ou protégé (protected) + //mais un champ peut-être aussi public ou internal + string mTitre; + + //un champ peut être initialisé dans sa déclaration (on parle d'initialiseur) + int mNombre = 1; + + //un champ peut être de type valeur... + int année; + + //... ou de type référence + Artiste mArtiste; + + //si un champ a un modifier readonly, il ne peut être initialisé que dans sa déclaration (initialiseur) ou dans le constructeur ("run-time constant") + readonly string mMaisonDeDisque = "IUT"; + + //si un champ a un modifier const, il ne peut être initialisé que dans sa déclaration ("compile-time constant") + const string mTruc = "non rien"; + + //object initializers + //peuvent ainsi être initialisés sans constructeurs + //attention : il ne vaut pas mieux mettre des membres en public. Cette méthode est donc surtout utile pour + // des propriétés publiques (cf. plus tard) + public int A + { + get; + set; + } + public int B; + public int C; + } + + class Artiste + { + //rien pour l'instant... + } + + class Program + { + static void Main(string[] args) + { + Disque d = new Disque(); + + //initializers + Disque d2 = new Disque { A = 1, B = 2, C = 3 }; + Disque d3 = new Disque() { A = 4, B = 5, C = 6 }; + } + } +} diff --git a/p03_POO/ex_014_003_ClasseChampInitialiseurs/ex_014_003_ClasseChampInitialiseurs.csproj b/p03_POO/ex_014_003_ClasseChampInitialiseurs/ex_014_003_ClasseChampInitialiseurs.csproj new file mode 100644 index 0000000..cd697af --- /dev/null +++ b/p03_POO/ex_014_003_ClasseChampInitialiseurs/ex_014_003_ClasseChampInitialiseurs.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_014_003_ClasseChampInitialiseurs + Exe + ex_014_003_ClasseChampInitialiseurs + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_014_004_constructeurs/Program.cs b/p03_POO/ex_014_004_constructeurs/Program.cs new file mode 100644 index 0000000..6c9bc23 --- /dev/null +++ b/p03_POO/ex_014_004_constructeurs/Program.cs @@ -0,0 +1,46 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +namespace ex_014_004_constructeurs +{ + internal class Disque + { + int mNombre = 1; + + readonly string mMaisonDeDisque = "IUT"; + + //constructeurs + //une classe peut avoir un ou plusieurs constructeurs, qui peuvent s'appeler à l'aide du mot clé this + //le constructeur sans paramètre est le constructeur par défaut + public Disque() + { + } + public Disque(string maison_de_disque) + { + mMaisonDeDisque = maison_de_disque; + } + public Disque(string maison_de_disque, int nombre) + : this(maison_de_disque) + { + mNombre = nombre; + } + } + + class Program + { + static void Main(string[] args) + { + Disque d = new Disque(); + Disque d2 = new Disque("Oh yes !"); + Disque d3 = new Disque("Arf no !", 0); + } + } +} diff --git a/p03_POO/ex_014_004_constructeurs/ex_014_004_constructeurs.csproj b/p03_POO/ex_014_004_constructeurs/ex_014_004_constructeurs.csproj new file mode 100644 index 0000000..d331e2a --- /dev/null +++ b/p03_POO/ex_014_004_constructeurs/ex_014_004_constructeurs.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_014_004_constructeurs + Exe + ex_014_004_constructeurs + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_014_005_methodes/Program.cs b/p03_POO/ex_014_005_methodes/Program.cs new file mode 100644 index 0000000..039fccd --- /dev/null +++ b/p03_POO/ex_014_005_methodes/Program.cs @@ -0,0 +1,58 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using static System.Console; + +namespace ex_014_005_methodes +{ + internal class Disque + { + //une méthode est définie juste après sa déclaration + //elle peut avoir aussi les modifieurs public, protected, private, internal + //elle peut être surchargée, tant que les paramètres sont différents (ref et out comptent) + public void Affiche() + { + WriteLine("Affiche()"); + } + public void Affiche(int bof) + { + WriteLine("Affiche(int bof)"); + } + public void Affiche(ref int bof) + { + WriteLine("Affiche(ref int bof)"); + } + + //constructeurs + //une classe peut avoir un ou plusieurs constructeurs, qui peuvent s'appeler à l'aide du mot clé this + //le constructeur sans paramètre est le constructeur par défaut + public Disque() + { + } + } + + class Artiste + { + //rien pour l'instant... + } + + class Program + { + static void Main(string[] args) + { + int a = 0; + Disque d = new Disque(); + d.Affiche(); + d.Affiche(a); + d.Affiche(ref a); + } + } +} diff --git a/p03_POO/ex_014_005_methodes/ex_014_005_methodes.csproj b/p03_POO/ex_014_005_methodes/ex_014_005_methodes.csproj new file mode 100644 index 0000000..d8eb499 --- /dev/null +++ b/p03_POO/ex_014_005_methodes/ex_014_005_methodes.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_014_005_methodes + Exe + ex_014_005_methodes + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_014_006_object_ToString/Program.cs b/p03_POO/ex_014_006_object_ToString/Program.cs new file mode 100644 index 0000000..6242fb5 --- /dev/null +++ b/p03_POO/ex_014_006_object_ToString/Program.cs @@ -0,0 +1,91 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using static System.Console; + +namespace ex_014_006_object_ToString +{ + //toutes les classes descendent de la classe Object. + //Object contient un constructeur, et les méthodes : Equals, GetType, et ToString + //ici nous réécrivons ToString pour les classes Disque et Livre et Equals pour la classe Livre + + class Disque + { + private string mArtiste; + string mTitre; + int mAnnéeCréation; + + public Disque(string titre, int année, string artiste) + { + mTitre = titre; + mAnnéeCréation = année; + mArtiste = artiste; + } + + //on réécrit ToString + public override string ToString() + { + return $"Le disque {mTitre} a été enregistré par {mArtiste} en {mAnnéeCréation}"; + } + } + + class Livre + { + protected string mTitre; + int mAnnéeSortie; + string mAuteur; + + public Livre(string titre, int année, string auteur) + { + mTitre = titre; + mAnnéeSortie = année; + mAuteur = auteur; + } + + //on réécrit ToString + public override string ToString() + { + return $"Le livre {mTitre} a été écrit par {mAuteur} en {mAnnéeSortie}"; + } + + //on réécrit Equals, ici on décide par exemple que l'année n'a pas d'importance (une nouvelle édition par exemple) + public override bool Equals(object obj) + { + if (mTitre == ((Livre)obj).mTitre && mAuteur == ((Livre)obj).mAuteur) + return true; + return false; + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Livre l = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + Disque d = new Disque("Underground", 2007, "Chris Potter"); + + Write($"{l.GetType().Name} : "); + WriteLine(l); + + Write($"{d.GetType().Name} : "); + WriteLine(d); + + Livre l2 = new Livre("Attenti al Gorilla", 1997, "Sandrone Dazieri"); + Livre l3 = new Livre("Attenti", 1995, "Sandrone Dazieri"); + if (l2.Equals(l)) + WriteLine("l2 = l"); + if (l3.Equals(l)) + WriteLine("l3 = l"); + } + } +} diff --git a/p03_POO/ex_014_006_object_ToString/ex_014_006_object_ToString.csproj b/p03_POO/ex_014_006_object_ToString/ex_014_006_object_ToString.csproj new file mode 100644 index 0000000..a446c53 --- /dev/null +++ b/p03_POO/ex_014_006_object_ToString/ex_014_006_object_ToString.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_014_006_object_ToString + Exe + ex_014_006_object_ToString + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_014_007_expression_bodied_methods/Program.cs b/p03_POO/ex_014_007_expression_bodied_methods/Program.cs new file mode 100644 index 0000000..157e116 --- /dev/null +++ b/p03_POO/ex_014_007_expression_bodied_methods/Program.cs @@ -0,0 +1,93 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using static System.Console; + +namespace ex_014_007_expression_bodied_methods +{ + class Rectangle + { + float mLargeur; + float mLongueur; + + public Rectangle(float largeur, float longueur) + { + mLargeur = largeur; + mLongueur = longueur; + } + + /// + /// une méthode simple ne renvoyant rien (void) et prenant un paramètre + /// + /// nouvelle largeur + public void ChangeLargeur(float largeur) + { + mLargeur = largeur; + } + + /// + /// une méthode très similaire à la précédente (ne rendant rien et prenant un paramètre) mais écrite avec une expression + /// Notez la flèche => + /// Marche bien pour les méthodes avec une seule instruction + /// + /// nouvelle longueur + public void ChangeLongeur(float longueur) => mLongueur = longueur; + + /// + /// méthode simple ne prenant rien et rendant un float + /// + /// l'aire de ce Rectangle + public float CalculeAire() + { + return mLargeur * mLongueur; + } + + /// + /// une méthode très similaire à la précédente (ne prenant rien et rendant un float) mais écrite avec une expression + /// Notez la flèche => + /// Notez l'absence du mot-clef return + /// Marche bien pour les méthodes avec une seule instruction + /// + /// le périmètre de ce Rectangle + public float CalculePérimètre() => 2 * (mLargeur + mLongueur); + } + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Rectangle r = new Rectangle(2, 3); + WriteLine("Rectangle r = new Rectangle(2, 3);"); + WriteLine($"r.CalculeAire() : {r.CalculeAire()} u²"); + WriteLine($"r.CalculePérimètre() : {r.CalculePérimètre()} u"); + r.ChangeLargeur(3); + r.ChangeLongeur(4); + WriteLine("r.ChangeLargeur(3);"); + WriteLine("r.ChangeLongeur(4);"); + WriteLine($"r.CalculeAire() : {r.CalculeAire()} u²"); + WriteLine($"r.CalculePérimètre() : {r.CalculePérimètre()} u"); + + WriteLine(); + WriteLine("où CalculeAire() est écrite classiquement :"); + WriteLine("public float CalculeAire() { return mLargeur * mLongueur; }"); + WriteLine(); + WriteLine("et CalculePérimètre() est écrite avec une expression :"); + WriteLine("public float CalculePérimètre() => 2*(mLargeur+mLongueur);"); + WriteLine(); + WriteLine("ChangeLargeur() est écrite classiquement :"); + WriteLine("public void ChangeLargeur(float largeur) { mLargeur = largeur; }"); + WriteLine(); + WriteLine("et ChangeLongeur() est écrite avec une expression :"); + WriteLine("public void ChangeLongeur(float longueur) => mLongueur = longueur;"); + } + } +} diff --git a/p03_POO/ex_014_007_expression_bodied_methods/ex_014_007_expression_bodied_methods.csproj b/p03_POO/ex_014_007_expression_bodied_methods/ex_014_007_expression_bodied_methods.csproj new file mode 100644 index 0000000..1e4976c --- /dev/null +++ b/p03_POO/ex_014_007_expression_bodied_methods/ex_014_007_expression_bodied_methods.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_014_007_expression_bodied_methods + Exe + ex_014_007_expression_bodied_methods + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_014_008_deconstruction/Program.cs b/p03_POO/ex_014_008_deconstruction/Program.cs new file mode 100644 index 0000000..21fcd23 --- /dev/null +++ b/p03_POO/ex_014_008_deconstruction/Program.cs @@ -0,0 +1,66 @@ +// ======================================================================== +// +// Copyright (C) 2017-2018 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2017-09-28 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_014_008_deconstruction +{ + /// + /// NOUVEAUTE C# 7.0 + /// + /// Comme les Tuples (cf. ex_004_009), n'importe quel type peut-être déconstruit, à l'aide d'une méthode de déconstruction + /// Dans la classe Nounours ci-dessous, la méthode Decontruct possède des variables en paramètres de sortie out permettant de déconstruire une instance de Nounours. + /// Le Main ci-dessous l'utilise. + /// + class Program + { + static void Main(string[] args) + { + Console.OutputEncoding = System.Text.Encoding.UTF8; + + //construction + Nounours monNounours = new Nounours("Chucky", 4, new DateTime(1988, 11, 9)); + + //déconstruction + monNounours.Deconstruct(out string leNom, out int leNbPoils, out DateTime laDateDeNaissance); + + WriteLine($"{leNom} a {leNbPoils} poils et est né en {laDateDeNaissance.Year}"); + + //on peut également ignorer certaines variables avec _ (discard) + monNounours.Deconstruct(out string leNom2, out _, out DateTime laDateDeNaissance2); + WriteLine($"{leNom2} est né en {laDateDeNaissance2.Year}"); + } + } + + class Nounours + { + private string nom; + + private int nbPoils; + + private DateTime naissance; + + public Nounours(string _nom, int _nbPoils, DateTime _naissance) + { + nom = _nom; + nbPoils = _nbPoils; + naissance = _naissance; + } + + public void Deconstruct(out string outNom, out int outNbPoils, out DateTime outNaissance) + { + outNom = nom; + outNbPoils = nbPoils; + outNaissance = naissance; + } + } +} diff --git a/p03_POO/ex_014_008_deconstruction/ex_014_008_deconstruction.csproj b/p03_POO/ex_014_008_deconstruction/ex_014_008_deconstruction.csproj new file mode 100644 index 0000000..a69c6ed --- /dev/null +++ b/p03_POO/ex_014_008_deconstruction/ex_014_008_deconstruction.csproj @@ -0,0 +1,6 @@ + + + Exe + net6.0 + + diff --git a/p03_POO/ex_015_001_static/Program.cs b/p03_POO/ex_015_001_static/Program.cs new file mode 100644 index 0000000..f2a6692 --- /dev/null +++ b/p03_POO/ex_015_001_static/Program.cs @@ -0,0 +1,114 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_015_001_static +{ + public class Etudiant + { + Random random = new Random(); + + public int GenereNoteAvecRandomNonStatic() + { + return random.Next(0, 21); + } + + static Random randomStatic; + + public int GenereNoteAvecRandomStatic() + { + return randomStatic.Next(0, 21); + } + + //un constructeur static est nécessairement privé et ne peut pas être appelé directement + //il sera appelé lors de la première construction d'un objet de ce type + static Etudiant() + { + randomStatic = new Random(); + //ici, il est évidemment préférable d'utiliser l'initialiseur plutôt que le constructeur pour Random + //mais c'est juste pour l'exemple d'un constructeur static + } + + //membre non statique + public string Année = "2013-2014"; + + //méthode non statique + public string GetAnnéeFormation() + { + //une méthode non statique peut utiliser aussi bien des membres non statiques que des membres statiques + return $"{Formation} ({Année})"; + } + + //membre statique (partagé par toutes les instances de cette classe) + public static string Formation = "DUT Informatique"; + + //méthode statique + public static string GetFormation() + { + //une méthode statique ne peut pas utiliser de membres non statiques + //return string.Format("{0} ({1})", Formation, Année); + + //une méthode statique ne peut utiliser que des membres statiques + return $"{Formation} ({Université})"; + } + + //un membre const est toujours statique, même si on ne le précise pas dans la syntaxe + public const string Université = "Université d'Auvergne"; + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Etudiant[] tableauEtudiants = new Etudiant[10]; + for (int i = 0; i < tableauEtudiants.Length; i++) + { + tableauEtudiants[i] = new Etudiant(); + } + + WriteLine("Méthode avec random non static"); + for (int i = 0; i < tableauEtudiants.Length; i++) + { + WriteLine($"L'étudiant {i} a obtenu la note de {tableauEtudiants[i].GenereNoteAvecRandomNonStatic()}/20"); + } + WriteLine(); + + WriteLine("Méthode avec random static"); + for (int i = 0; i < tableauEtudiants.Length; i++) + { + WriteLine($"L'étudiant {i} a obtenu la note de {tableauEtudiants[i].GenereNoteAvecRandomStatic()}/20"); + } + WriteLine(); + + WriteLine("Année"); + //pour appeler les membres non statiques et les méthodes non statiques, + //une instance est obligatoire + Etudiant étudiant = new Etudiant(); + WriteLine(étudiant.Année); + WriteLine(étudiant.GetAnnéeFormation()); + WriteLine(); + + WriteLine("Formation"); + //pour appeler les membres statiques et les méthodes statiques, + //on utiliser les méthodes sur le type lui-même, sans instances + WriteLine(Etudiant.Formation); + WriteLine(Etudiant.GetFormation()); + WriteLine(); + + WriteLine("Autre exemple de propriété statique : DateTime.Now"); + WriteLine($"DateTime.Now = {DateTime.Now}"); + } + } +} diff --git a/p03_POO/ex_015_001_static/ex_015_001_static.csproj b/p03_POO/ex_015_001_static/ex_015_001_static.csproj new file mode 100644 index 0000000..0aa8a4c --- /dev/null +++ b/p03_POO/ex_015_001_static/ex_015_001_static.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_015_001_static + Exe + ex_015_001_static + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_015_002_ordreAppelStatic/Program.cs b/p03_POO/ex_015_002_ordreAppelStatic/Program.cs new file mode 100644 index 0000000..a9fd12c --- /dev/null +++ b/p03_POO/ex_015_002_ordreAppelStatic/Program.cs @@ -0,0 +1,58 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using static System.Console; + +namespace ex_015_002_ordreAppelStatic +{ + class SansIntérêt + { + static int n = 0; + + public SansIntérêt(string nom) + { + n++; + WriteLine($"exécution du constructeur de l'instance sans intérêt n°{n}({nom})"); + } + } + + class UneClasse + { + public static SansIntérêt mMembreStatique1 = new SansIntérêt("membre statique 1"); + public static SansIntérêt mMembreStatique2 = new SansIntérêt("membre statique 2"); + static UneClasse() + { + WriteLine("exécution du constructeur par défaut statique de UneClasse"); + } + public SansIntérêt mMembreNonStatique1 = new SansIntérêt("membre instance 1"); + + public SansIntérêt mMembreNonStatique2 = new SansIntérêt("membre instance 2"); + + + + public UneClasse() + { + WriteLine("exécution du constructeur de l'instance de UneClasse"); + } + + + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + UneClasse c = new UneClasse(); + } + } +} diff --git a/p03_POO/ex_015_002_ordreAppelStatic/ex_015_002_ordreAppelStatic.csproj b/p03_POO/ex_015_002_ordreAppelStatic/ex_015_002_ordreAppelStatic.csproj new file mode 100644 index 0000000..68fb9bc --- /dev/null +++ b/p03_POO/ex_015_002_ordreAppelStatic/ex_015_002_ordreAppelStatic.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_015_002_ordreAppelStatic + Exe + ex_015_002_ordreAppelStatic + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_015_003_singleton/Program.cs b/p03_POO/ex_015_003_singleton/Program.cs new file mode 100644 index 0000000..41b0dee --- /dev/null +++ b/p03_POO/ex_015_003_singleton/Program.cs @@ -0,0 +1,47 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using static System.Console; + +namespace ex_015_003_singleton +{ + //le patron de conception Singleton permet de restreindre le nombre d'instances à 1 + public class IutClermont + { + //le constructeur est privé et ne peut pas être appelé en dehors de la classe + private IutClermont() + { + Description = "Meilleur IUT d'Informatique de France"; + } + + //membre non statique, utilisable par les instances + public string Description; + + //la classe possède un membre statique du type de la classe qui lui, peut appeler le constructeur privé pour se construire + static IutClermont mInstance = new IutClermont(); + + //méthode statique de la classe, rendant l'instance statique de cette classe + public static IutClermont GetInstance() + { + return mInstance; + } + } + + class Program + { + static void Main(string[] args) + { + //IutClermont iut = new IutClermont(); //interdit + IutClermont iut = IutClermont.GetInstance(); + WriteLine(iut.Description); + } + } +} diff --git a/p03_POO/ex_015_003_singleton/ex_015_003_singleton.csproj b/p03_POO/ex_015_003_singleton/ex_015_003_singleton.csproj new file mode 100644 index 0000000..f441ff4 --- /dev/null +++ b/p03_POO/ex_015_003_singleton/ex_015_003_singleton.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_015_003_singleton + Exe + ex_015_003_singleton + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_015_004_using_static/Program.cs b/p03_POO/ex_015_004_using_static/Program.cs new file mode 100644 index 0000000..3d47ecb --- /dev/null +++ b/p03_POO/ex_015_004_using_static/Program.cs @@ -0,0 +1,126 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-23 +// +// ======================================================================== + +using System; +using static System.Console; +using static ex_015_004_using_static.Etudiant; +using static ex_015_004_using_static.BacOrigine; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ex_015_004_using_static +{ + public class Etudiant + { + Random random = new Random(); + + public int GenereNoteAvecRandomNonStatic() + { + return random.Next(0, 21); + } + + static Random randomStatic; + + public int GenereNoteAvecRandomStatic() + { + return randomStatic.Next(0, 21); + } + + //un constructeur static est nécessairement privé et ne peut pas être appelé directement + //il sera appelé lors de la première construction d'un objet de ce type + static Etudiant() + { + randomStatic = new Random(); + //ici, il est évidemment préférable d'utiliser l'initialiseur plutôt que le constructeur pour Random + //mais c'est juste pour l'exemple d'un constructeur static + } + + //membre non statique + public string Année = "2013-2014"; + + //méthode non statique + public string GetAnnéeFormation() + { + //une méthode non statique peut utiliser aussi bien des membres non statiques que des membres statiques + return $"{Formation} ({Année})"; + } + + //membre statique (partagé par toutes les instances de cette classe) + public static string Formation = "DUT Informatique"; + + //méthode statique + public static string GetFormation() + { + //une méthode statique ne peut pas utiliser de membres non statiques + //return string.Format("{0} ({1})", Formation, Année); + + //une méthode statique ne peut utiliser que des membres statiques + return $"{Formation} ({Université})"; + } + + //un membre const est toujours statique, même si on ne le précise pas dans la syntaxe + public const string Université = "Université d'Auvergne"; + + public BacOrigine Origine; + } + + public enum BacOrigine + { + Inconnu, + S, + ES, + L, + STI2D + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + WriteLine("sans : using static ex_015_004_using_static.Etudiant; il faudrait écrire :"); + WriteLine($"Etudiant.Formation : {Etudiant.Formation}"); + WriteLine($"Etudiant.Université : {Etudiant.Université}"); + WriteLine($"Etudiant.GetFormation() : {Etudiant.GetFormation()}"); + WriteLine(); + WriteLine("grâce à : using static ex_015_004_using_static.Etudiant; on peut simplement écrire :"); + WriteLine($"Formation : {Formation}"); + WriteLine($"Université : {Université}"); + WriteLine($"GetFormation() : {GetFormation()}"); + WriteLine(); + WriteLine("C'est d'ailleurs la même chose pour l'utilisation de la Console :"); + WriteLine("sans : using static System.Console; il faudrait écrire :"); + string prout = "prout"; + WriteLine($"Console.WriteLine(\"prout\");"); + Console.WriteLine(prout); + WriteLine(); + WriteLine("grâce à : using static System.Console; on peut écrire :"); + WriteLine($"WriteLine(\"prout\");"); + WriteLine(prout); + WriteLine(); + WriteLine("Marche également avec les enum"); + WriteLine("sans : using static ex_015_004_using_static.BacOrigine; il faudrait écrire"); + WriteLine("e.Origine = BacOrigine.STI2D;"); + Etudiant e = new Etudiant(); + e.Origine = BacOrigine.STI2D; + WriteLine(); + WriteLine("grâce à : using static ex_015_004_using_static.BacOrigine; on peut écrire"); + WriteLine("e.Origine = STI2D;"); + e.Origine = STI2D; + WriteLine(); + WriteLine("Tout cela marche très bien, tant que le compilateur ne détecte aucune ambiguité"); + + } + } +} diff --git a/p03_POO/ex_015_004_using_static/ex_015_004_using_static.csproj b/p03_POO/ex_015_004_using_static/ex_015_004_using_static.csproj new file mode 100644 index 0000000..100420c --- /dev/null +++ b/p03_POO/ex_015_004_using_static/ex_015_004_using_static.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_015_004_using_static + Exe + ex_015_004_using_static + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_016_001_getters_setters_methods/Program.cs b/p03_POO/ex_016_001_getters_setters_methods/Program.cs new file mode 100644 index 0000000..04b8180 --- /dev/null +++ b/p03_POO/ex_016_001_getters_setters_methods/Program.cs @@ -0,0 +1,117 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-24 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_016_001_getters_setters_methods +{ + class Nounours + { + //un getter permet de lire un champ privé + public string GetNom() + { + return mNom; + } + + //un setter permet de modifier un champ privé + public void SetNom(string value) + { + mNom = value; + } + private string mNom; + + //on peut ainsi, protéger nos champs privés de différentes manières + public int GetTaille() + { + return mTaille; + } + public void SetTaille(int value) + { + if (value > 0) + { + mTaille = value; + } + } + private int mTaille; + + public int GetPoils() + { + return mPoils; + } + private void SetPoils(int value) + { + if (value >= 0) + { + mPoils = value; + } + } + private int mPoils; + + //on peut aussi avoir un getter uniquement et transformer ainsi le champ en lecture seule + //ou un setter privé comme pour mPoils + public DateTime GetDateDeNaissance() + { + return mDateDeNaissance; + } + private DateTime mDateDeNaissance; + + //ou en écriture seule... + + //un getter n'est pas forcément lié à un membre, mais peut simuler la lecture d'un membre qui est alors calculé à la volée + public float GetPoilsParCm() + { + return (float)mPoils / (float)mTaille; + } + + //on utilise les setters pour initialiser les membres + public Nounours(string nom, int taille, DateTime naissance, int poils) + { + SetNom(nom); + SetTaille(taille); + mDateDeNaissance = naissance; + SetPoils(poils); + } + + //getter et setter statiques + public static string GetDéfinition() + { + return mDéfinition; + } + public static void SetDéfinition(string value) + { + mDéfinition = value; + } + private static string mDéfinition = "Mot enfantin pour désigner un ours en peluche"; + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //utilisation des getters et setters + Nounours nounours = new Nounours("ours", 42, DateTime.Today, 30000); + WriteLine("Nounours nounours = new Nounours(\"ours\", 42, DateTime.Today, 30000);"); + WriteLine($"Nom : {nounours.GetNom()}"); + WriteLine($"Poils : {nounours.GetPoils()}"); + WriteLine($"Taille : {nounours.GetTaille()}"); + WriteLine($"Date de naissance : {nounours.GetDateDeNaissance()}"); + WriteLine($"Poils par cm : {nounours.GetPoilsParCm()}"); + WriteLine("nounours.SetTaille(41);"); + nounours.SetTaille(41); + WriteLine($"Taille : {nounours.GetTaille()}"); + WriteLine($"Poils par cm : {nounours.GetPoilsParCm()}"); + WriteLine($"Définition : {Nounours.GetDéfinition()}"); + } + } +} diff --git a/p03_POO/ex_016_001_getters_setters_methods/ex_016_001_getters_setters_methods.csproj b/p03_POO/ex_016_001_getters_setters_methods/ex_016_001_getters_setters_methods.csproj new file mode 100644 index 0000000..007d93e --- /dev/null +++ b/p03_POO/ex_016_001_getters_setters_methods/ex_016_001_getters_setters_methods.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_016.0.6_getters_setters_methods + Exe + ex_016.0.6_getters_setters_methods + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_016_002_properties/Program.cs b/p03_POO/ex_016_002_properties/Program.cs new file mode 100644 index 0000000..408acc4 --- /dev/null +++ b/p03_POO/ex_016_002_properties/Program.cs @@ -0,0 +1,141 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-25 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_016_002_properties +{ + class Nounours + { + //une propriété ressemble à un champ de l'extérieur mais se comporte comme une méthode à l'intérieur + //on l'utilise comme accesseur sur un champ privé pour garantir l'encapsulation + //en lecture/écriture, lecture ou écriture + //on l'associe donc généralement à un champ privé + public string Nom + { + get //public string GetNom() + { + return mNom; + } + set //public void SetNom(string value) + { + mNom = value; + } + } + private string mNom; + + //on peut en conséquence, protéger nos champs privés de différentes manières + public int Taille + { + get + { + return mTaille; + } + set + { + if (value > 0) + { + mTaille = value; + } + } + } + private int mTaille = 100; + + //on peut aussi avoir une propriété en lecture seule + public DateTime DateDeNaissance + { + get + { + return mDateDeNaissance; + } + } + private DateTime mDateDeNaissance; + + //ou en écriture seule + + //automatic properties + //on peut aussi définir une propriété sans membre privé si le getter et le setter sont basiques (aux modifiers près) + //(ne marche pas sur les structures) + public int Poils + { + get; + private set; + } + + //calculated properties + //une propriété n'est pas forcément liée à un membre privé (ou protégé), elle est peut être calculée à partir d'autres membres ou propriétés + public float PoilsParCm + { + get + { + return (float)Poils / Taille; + } + } + + //expression-bodied read-only properties (C#6) + // une propriété calculée ou read-only peut aussi être déclarée directement à l'aide d'une expression + // notez qu'il n'est plus nécessaire d'utiliser les { }, le mot-clef get, et le mot-clef return + public int Age => DiffYears + (DateDeNaissance.AddYears(DiffYears) > DateTime.Today ? -1 : 0); + //et une petite propriété privée rapide pour simplifier l'écriture de la propriété précédente + private int DiffYears => DateTime.Today.Year - DateDeNaissance.Year; + + // depuis C#6 on peut également initialiser une propriété automatique juste après l'avoir écrite. + // C'est notamment très pratique pour les propriétés automatiques en lecture seule. + public string Odeur { get; set; } = "chien mouillé"; + + public Nounours(string nom, int taille, DateTime naissance, int poils) + { + Nom = nom; + Taille = taille; + mDateDeNaissance = naissance; + Poils = poils; + } + + //propriété statique + public static string Définition + { + get + { + return mDéfinition; + } + set + { + mDéfinition = value; + } + } + private static string mDéfinition = "Mot enfantin pour désigner un ours en peluche"; + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //les propriétés s'utilisent comme des membres + Nounours nounours = new Nounours("ours", 42, new DateTime(2015, 9, 26), 30000); + WriteLine("Nounours nounours = new Nounours(\"ours\", 42, DateTime.Today, 30000);"); + WriteLine($"Nom : {nounours.Nom}"); + WriteLine($"Poils : {nounours.Poils}"); + WriteLine($"Taille : {nounours.Taille}"); + WriteLine($"Age : {nounours.Age}"); + WriteLine($"Odeur : {nounours.Odeur}"); + WriteLine($"Date de naissance : {nounours.DateDeNaissance}"); + WriteLine($"Poils par cm : {nounours.PoilsParCm}"); + WriteLine("nounours.Taille = 41;"); + nounours.Taille = 41; + WriteLine($"Taille : {nounours.Taille}"); + WriteLine($"Poils par cm : {nounours.PoilsParCm}"); + WriteLine($"Définition : {Nounours.Définition}"); + } + } +} diff --git a/p03_POO/ex_016_002_properties/ex_016_002_properties.csproj b/p03_POO/ex_016_002_properties/ex_016_002_properties.csproj new file mode 100644 index 0000000..902b14a --- /dev/null +++ b/p03_POO/ex_016_002_properties/ex_016_002_properties.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_016_002_properties + Exe + ex_016_002_properties + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_016_003_indexers/Program.cs b/p03_POO/ex_016_003_indexers/Program.cs new file mode 100644 index 0000000..851c57d --- /dev/null +++ b/p03_POO/ex_016_003_indexers/Program.cs @@ -0,0 +1,232 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_016_003_indexers +{ + class Nounours + { + //une propriété + public string Nom + { + get + { + return mNom; + } + set + { + mNom = value; + } + } + private string mNom; + } + + //classe possédant des indexeurs + class MonLit + { + Nounours[] mNounours; + + //constructeur + public MonLit(int nombre) + { + mNounours = new Nounours[nombre]; + } + + //une propriété de plus + public int NombreNounours + { + get + { + return mNounours.Length; + } + } + + /// + /// indexeur permettant de récupérer ou d'écrire le (index)ième nounours dans le tableau mNounours + /// + /// index du nounours à récupérer ou écrire + /// rend le (index)ième nounours ou null si l'index n'est pas valide + public Nounours this[int index] + { + get + { + if (index >= NombreNounours || index < 0) + { + return null; + } + return mNounours[index]; + } + set + { + if (index < NombreNounours && index >= 0) + { + mNounours[index] = value; + } + } + } + + /// + /// indexeur en lecture seule permettant de récupérer un nounours dans le tableau mNounours à partir de son nom + /// + /// nom du Nounours recherché + /// le nounours avec ce nom, ou null si le nom n'est pas reconnu + public Nounours this[string nom] + { + get + { + foreach (Nounours n in mNounours) + { + if (n.Nom == nom) + { + return n; + } + } + return null; + } + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + WriteLine("Création d'un lit avec trois nounours"); + MonLit monlit = new MonLit(3); + + //utilisation de l'indexeur this[int] en écriture (set) + monlit[0] = new Nounours { Nom = "zinzin" }; + monlit[1] = new Nounours { Nom = "rooooo" }; + monlit[2] = new Nounours { Nom = "argh" }; + + WriteLine("contenu du 1er lit"); + for (int i = 0; i < monlit.NombreNounours; i++) + { + //utilisation de l'indexeur this[int] en lecture (get) + WriteLine(monlit[i].Nom); + } + + ReadLine(); + + WriteLine("modification d'un nounours du lit avec l'indexeur"); + + //utilisation de l'idexeur this[string] + if (monlit["rooooo"] != null) + { + //utilisation de l'idexeur this[string] + monlit["rooooo"].Nom = "zibaouin"; + } + + WriteLine("contenu du lit"); + for (int i = 0; i < monlit.NombreNounours; i++) + { + //utilisation de l'idexeur this[int] en lecture + WriteLine(monlit[i].Nom); + } + + ReadLine(); + WriteLine("création d'une maison avec deux lits : 1er lit = le précédent, 2ème lit de 4 nouveaux nounours"); + MaMaison maison = new MaMaison(2); + //utilisation de l'indexeur simple de MaMaison this[int] + maison[0] = monlit; + maison[1] = new MonLit(4); + //notez que maison[1, 0] = new Nounours(); ne compile pas, car l'indexeur n'a pas de 'set' + //mais on peut accéder quand même à maison[1][0] car on accède à la référence maison[1] de type MonLit et de là, grâce à l'indexeur, + //au nounours maison[1][0]... donc ... ATTENTION AUX REFERENCES PUBLIQUES DANS VOTRE API ! + + //utilisation de l'indexeur this[int] de MaMaison puis de l'indexeur this[int] de MonLit + maison[1][0] = new Nounours(); + //utilisation de l'indexeur double this[int, int] de MaMaison + maison[1, 0].Nom = "Nigel"; + maison[1][1] = new Nounours(); + maison[1, 1].Nom = "David"; + maison[1][2] = new Nounours(); + maison[1, 2].Nom = "Derek"; + maison[1][3] = new Nounours(); + maison[1, 3].Nom = "Ian"; + WriteLine("contenu du lit"); + for (int i = 0; i < maison.NbreLits; i++) + { + WriteLine($"lit n°{(i + 1)}"); + for (int j = 0; j < maison[i].NombreNounours; j++) + { + WriteLine(maison[i, j].Nom); + } + WriteLine(); + } + } + } + + //exemple d'indexeur à 2 variables + class MaMaison + { + MonLit[] mLits; + + public MaMaison(int nombre) + { + mLits = new MonLit[nombre]; + } + + //une propriété en lecture seule + public int NbreLits + { + get + { + return mLits.Length; + } + } + + + /// + /// un indexeur simple + /// + /// indice du lit à atteindre dans le tableau mLits + /// + public MonLit this[int lit] + { + get + { + if (lit >= NbreLits || lit < 0) + { + return null; + } + return mLits[lit]; + } + set + { + if (lit < NbreLits && lit >= 0) + { + mLits[lit] = value; + } + } + } + + /// + /// un indexeur à double entrée + /// + /// indice du lit à atteindre dans le tableau mLits + /// indice du nounours à atteindre dans le tableau mNounours de mLits[lit] + /// + public Nounours this[int lit, int nounours] + { + get + { + if (lit >= NbreLits || lit < 0 || nounours >= mLits[lit].NombreNounours || nounours < 0) + { + return null; + } + return mLits[lit][nounours]; + } + } + } +} diff --git a/p03_POO/ex_016_003_indexers/ex_016_003_indexers.csproj b/p03_POO/ex_016_003_indexers/ex_016_003_indexers.csproj new file mode 100644 index 0000000..7c56dc3 --- /dev/null +++ b/p03_POO/ex_016_003_indexers/ex_016_003_indexers.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_016_003_indexers + Exe + ex_016_003_indexers + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_016_004_readonly/Program.cs b/p03_POO/ex_016_004_readonly/Program.cs new file mode 100644 index 0000000..888b4ef --- /dev/null +++ b/p03_POO/ex_016_004_readonly/Program.cs @@ -0,0 +1,69 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_016_004_readonly +{ + /// + /// classe représentant un disque + /// + class Disque + { + /// + /// artiste du disque (en readonly) (public pour la simplicité de l'exemple !) + /// + public readonly Artiste mArtiste; + + /// + /// année de sortie (en readonly) (public pour la simplicité de l'exemple !) + /// + public readonly int mAnnée; + + /// + /// constructeur + /// + /// + /// + public Disque(Artiste artiste, int année) + { + mArtiste = artiste; + mAnnée = année; + } + } + + /// + /// classe représentant un artiste + /// + class Artiste + { + /// + /// nom de l'artiste (public pour la simplicité de l'exemple !) + /// + public string mName; + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Disque d = new Disque(new Artiste { mName = "Miles Davis" }, 1956); + WriteLine($"artiste : {d.mArtiste.mName}; année : {d.mAnnée}"); + //d.mAnnée = 1951; // ne compile pas (pas d'assignation possible car readonly) + //d.mArtiste = new Artiste { mName = "Charlie Parker" };// ne compile pas (pas d'assignation possible car readonly) + d.mArtiste.mName = "Charlie Parker"; //compile par l'adresse mArtiste n'a pas changé (readonly), mais le contenu pointé par la référence + // n'est pas en readonly et peut donc être modifié + WriteLine($"artiste : {d.mArtiste.mName}; année : {d.mAnnée}"); + } + } +} diff --git a/p03_POO/ex_016_004_readonly/ex_016_004_readonly.csproj b/p03_POO/ex_016_004_readonly/ex_016_004_readonly.csproj new file mode 100644 index 0000000..6efa03b --- /dev/null +++ b/p03_POO/ex_016_004_readonly/ex_016_004_readonly.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_016_004_readonly + Exe + ex_016_004_readonly + 5.0.0 + false + false + false + + diff --git a/p03_POO/ex_016_005_partial/MaClasse.QqsDétails.cs b/p03_POO/ex_016_005_partial/MaClasse.QqsDétails.cs new file mode 100644 index 0000000..c796fc1 --- /dev/null +++ b/p03_POO/ex_016_005_partial/MaClasse.QqsDétails.cs @@ -0,0 +1,23 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MaClasse.QqsDétails.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +namespace ex_016_005_partial +{ + partial class MaClasse + { + public int N3 + { + get; + set; + } + + } +} diff --git a/p03_POO/ex_016_005_partial/MaClasse.cs b/p03_POO/ex_016_005_partial/MaClasse.cs new file mode 100644 index 0000000..87c1d21 --- /dev/null +++ b/p03_POO/ex_016_005_partial/MaClasse.cs @@ -0,0 +1,33 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MaClasse.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +namespace ex_016_005_partial +{ + partial class MaClasse + { + public int N1 + { + get; + set; + } + public int N2 + { + get; + set; + } + + public override string ToString() + { + return $"{N1} {N2} {N3}"; + } + + } +} diff --git a/p03_POO/ex_016_005_partial/Program.cs b/p03_POO/ex_016_005_partial/Program.cs new file mode 100644 index 0000000..fc8fbb8 --- /dev/null +++ b/p03_POO/ex_016_005_partial/Program.cs @@ -0,0 +1,27 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_016_005_partial +{ + class Program + { + static void Main(string[] args) + { + MaClasse c = new MaClasse(); + c.N1 = 1; + c.N2 = 2; + c.N3 = 3; + WriteLine(c); + } + } +} diff --git a/p03_POO/ex_016_005_partial/ex_016_005_partial.csproj b/p03_POO/ex_016_005_partial/ex_016_005_partial.csproj new file mode 100644 index 0000000..7f67816 --- /dev/null +++ b/p03_POO/ex_016_005_partial/ex_016_005_partial.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_016_005_partial + Exe + ex_016_005_partial + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_016_006_local_functions/Program.cs b/p03_POO/ex_016_006_local_functions/Program.cs new file mode 100644 index 0000000..7ce0d0c --- /dev/null +++ b/p03_POO/ex_016_006_local_functions/Program.cs @@ -0,0 +1,139 @@ +// ======================================================================== +// +// Copyright (C) 2017-2018 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2017-10-02 +// +// ======================================================================== + +using System.Linq; +using static System.Console; + +namespace ex_016_006_local_functions +{ + /// + /// Pour plus de lisibilité, on ajoute régulièrement des méthodes privées à nos classes pour permettre de décomposer des algorithmes plus complexes, réaliser une récursivité + /// ou encore appeler plusieurs fois un même morceau d'algorithme (dans des tests par exemple). + /// Parfois, ces méthodes privées ne sont appelées que dans une seule méthode, et alourdisse la classe d'une méthode de plus, ce qui diminue un peu la visibilité des autres méthodes. + /// + /// Depuis C# 7.0, il est maintenant possible de définir des méthodes privées à l'intérieur d'autres méthodes. Le compilateur les traitera comme d'autres méthodes privées dont la + /// visibilité serait limitée à la méthode dans laquelle elle est définie. + /// Ceci pouvait déjà être fait avec des délégués, à quelques détails près, mais cette forme peut parfois être plus lisible et permet d'utiliser les paramètres ref et out. + /// + /// Dans l'exemple suivant, on réalise une méthode testant si une chaîne de caractères est un palindrome en utilisant une méthode privée + /// pour tester l'égalité du premier et du dernier caractère. Deux méthodes sont utilisées (sans et avec récursivité). + /// Ensuite, on utilise une troisième méthode privée au sein du test pour tester plusieurs fois si des chaînes de caractères sont des palindromes en utilisant la méthode précédente. + /// + + static class StringUtils + { + /// + /// méthode testant sur un mot est un palindrome en utilisant une méthode locale + /// + /// mot à tester + /// + public static bool IsPalindrome(string word) + { + //teste si le mot est blanc ou nul + if (string.IsNullOrWhiteSpace(word)) return false; + + bool result = true; + + //utilisation de la méthode locale + while ((result = CheckBoundaries(ref word)) && word.Length > 2) ; + + return result; + + //définition ici de la méthode locale, imbriquée dans la méthode IsPalindrome + bool CheckBoundaries(ref string str) + { + str = str.Trim(); + if (str[0] != str.Last()) return false; + str = str.Substring(1, str.Length - 2); + return true; + } + } + + /// + /// méthode testant sur un mot est un palindrome en utilisant une méthode locale + /// + /// mot à tester + /// + public static bool IsPalindrome2(string word) + { + //teste si le mot est blanc ou nul + if (string.IsNullOrWhiteSpace(word)) return false; + + //utilisation de la méthode locale + return CheckBoundaries(word); + + //définition de la méthode locale + bool CheckBoundaries(string str) + { + str = str.Trim(); + if (str[0] != str.Last()) return false; + str = str.Substring(1, str.Length - 2); + if (str.Length > 2) + return CheckBoundaries(str); + return true; + } + } + } + + class Program + { + static void Main(string[] args) + { + TestIsPalindrome(); + } + + /// + /// teste les méthodes IsPalindrome et IsPalindrome2 + /// Comme on réalise plusieurs fois les mêmes actions, on crée une méthode locale pour l'ensemble des tests. + /// Pratique dans les tests unitaires notamment. + /// + static void TestIsPalindrome() + { + TestAWord("abcdef"); + TestAWord("abcba"); + TestAWord("abccba"); + + TestAWord2("abcdef"); + TestAWord2("abcba"); + TestAWord2("abccba"); + + void TestAWord(string word) + { + WriteLine($"TEST DE LA METHODE IsPalindrome AVEC LE MOT : {word}"); + bool result = StringUtils.IsPalindrome(word); + if (result) + { + WriteLine($"Le mot {word} est un palindrome"); + } + else + { + WriteLine($"Le mot {word} n'est pas un palindrome"); + } + WriteLine(); + } + + void TestAWord2(string word) + { + WriteLine($"TEST DE LA METHODE IsPalindrome2 AVEC LE MOT : {word}"); + bool result = StringUtils.IsPalindrome2(word); + if (result) + { + WriteLine($"Le mot {word} est un palindrome"); + } + else + { + WriteLine($"Le mot {word} n'est pas un palindrome"); + } + WriteLine(); + } + } + } +} diff --git a/p03_POO/ex_016_006_local_functions/ex_016_006_local_functions.csproj b/p03_POO/ex_016_006_local_functions/ex_016_006_local_functions.csproj new file mode 100644 index 0000000..a69c6ed --- /dev/null +++ b/p03_POO/ex_016_006_local_functions/ex_016_006_local_functions.csproj @@ -0,0 +1,6 @@ + + + Exe + net6.0 + + diff --git a/p03_POO/ex_017_001_heritage_syntaxe/Program.cs b/p03_POO/ex_017_001_heritage_syntaxe/Program.cs new file mode 100644 index 0000000..015b7f3 --- /dev/null +++ b/p03_POO/ex_017_001_heritage_syntaxe/Program.cs @@ -0,0 +1,87 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_017_001_heritage_syntaxe +{ + //classe mère + //notez que les champs private ne sont pas accessibles par les classes filles, + //alors que les champs protected sont toujours invisibles de l'extérieur, mais visibles dans les classes filles + class MediaObjet + { + protected string mTitre; + protected int mAnnéeCréation; + + public MediaObjet(string titre, int année) + { + mTitre = titre; + mAnnéeCréation = année; + } + + public void Affiche() + { + WriteLine($"Ce média s'intitule {mTitre} et a été créé en {mAnnéeCréation}"); + } + } + + //une classe fille + class Disque : MediaObjet + { + private string mArtiste; + + //notez de quelle manière on appelle le constructeur de la classe mère avec base + public Disque(string titre, int année, string artiste) + : base(titre, année) + { + mArtiste = artiste; + } + + //méthode redéfinie + public void Affiche() + { + WriteLine($"Le disque {mTitre} a été enregistré par {mArtiste} en {mAnnéeCréation}"); + } + } + + //une autre classe fille + class Livre : MediaObjet + { + private string mAuteur; + + public Livre(string titre, int année, string auteur) + : base(titre, année) + { + mAuteur = auteur; + } + + public void Affiche() + { + WriteLine($"Le livre {mTitre} a été écrit par {mAuteur} en {mAnnéeCréation}"); + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Livre l = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + Disque d = new Disque("Underground", 2007, "Chris Potter"); + MediaObjet mo = new MediaObjet("La Grande Vadrouille", 1966); + + l.Affiche(); + d.Affiche(); + mo.Affiche(); + } + } +} diff --git a/p03_POO/ex_017_001_heritage_syntaxe/ex_017_001_heritage_syntaxe.csproj b/p03_POO/ex_017_001_heritage_syntaxe/ex_017_001_heritage_syntaxe.csproj new file mode 100644 index 0000000..40167c6 --- /dev/null +++ b/p03_POO/ex_017_001_heritage_syntaxe/ex_017_001_heritage_syntaxe.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_017_001_heritage_syntaxe + Exe + ex_017_001_heritage_syntaxe + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_017_002_redefinitionDeMethodes/Program.cs b/p03_POO/ex_017_002_redefinitionDeMethodes/Program.cs new file mode 100644 index 0000000..046ef7c --- /dev/null +++ b/p03_POO/ex_017_002_redefinitionDeMethodes/Program.cs @@ -0,0 +1,111 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_017_002_redefinitionDeMethodes +{ + //classe mère + //notez que les champs ne sont plus private mais protected (toujours invisibles de l'extérieur, mais visibles dans les classes filles) + class MediaObjet + { + protected string mTitre; + protected int mAnnéeCréation; + + public MediaObjet(string titre, int année) + { + mTitre = titre; + mAnnéeCréation = année; + } + + public void Affiche() + { + WriteLine($"Ce média s'intitule {mTitre} et a été créé en {mAnnéeCréation}"); + } + } + + //une classe fille + class Disque : MediaObjet + { + private string mArtiste; + + //notez de quelle manière on appelle le constructeur de la classe mère avec base + public Disque(string titre, int année, string artiste) + : base(titre, année) + { + mArtiste = artiste; + } + + //méthode redéfinie + public new void Affiche() + { + WriteLine($"Le disque {mTitre} a été enregistré par {mArtiste} en {mAnnéeCréation}"); + } + } + + //une autre classe fille + class Livre : MediaObjet + { + private string mAuteur; + + public Livre(string titre, int année, string auteur) + : base(titre, année) + { + mAuteur = auteur; + } + + public new void Affiche() + { + WriteLine($"Le livre {mTitre} a été écrit par {mAuteur} en {mAnnéeCréation}"); + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //ici pas de pb : + + //l est de type Livre (construit avec Livre) et appelle Affiche de Livre + Livre l = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + l.Affiche(); + + //d est de type Disque (construit avec Disque) et appelle Affiche de Disque + Disque d = new Disque("Underground", 2007, "Chris Potter"); + d.Affiche(); + + //mo est de type MediaObjet (construit avec MediaObjet) et appelle Affiche de MediaObjet + MediaObjet mo = new MediaObjet("La Grande Vadrouille", 1966); + mo.Affiche(); + + //modifions un peu à présent : + + //mo1 est de type MediaObjet et construit avec le constructeur de MediaObjet, il appelle Affiche de MediaObjet + MediaObjet mo1 = new MediaObjet("La Grande Vadrouille", 1966); + mo1.Affiche(); + //mo2 est de type MediaObjet mais construit avec le constructeur de Libre, il appelle Affiche de MediaObjet + MediaObjet mo2 = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + mo2.Affiche(); + //mo2 est de type MediaObjet mais construit avec le constructeur de Disque, il appelle Affiche de MediaObjet + MediaObjet mo3 = new Disque("Underground", 2007, "Chris Potter"); + mo3.Affiche(); + //c'est donc le type qui compte pour savoir quelle méthode appeler, quel que soit le constructeur. + //attention, on ne peut pas appeler n'importe quel constructeur ! + //1 Livre est un MediaObjet donc on peut construire un Livre et l'utiliser comme un MediaObjet + //mais un MediaObjet n'est pas obligatoirement un Livre, on ne peut donc pas construire un Livre avec le constructeur d'un MediaObjet + + //on peut toutefois reconnaître le "vrai" type (celui "du" au constructeur) à l'aide des fonctions virtuelles. + // cf. exemple polymorphisme. + } + } +} diff --git a/p03_POO/ex_017_002_redefinitionDeMethodes/ex_017_002_redefinitionDeMethodes.csproj b/p03_POO/ex_017_002_redefinitionDeMethodes/ex_017_002_redefinitionDeMethodes.csproj new file mode 100644 index 0000000..35ed018 --- /dev/null +++ b/p03_POO/ex_017_002_redefinitionDeMethodes/ex_017_002_redefinitionDeMethodes.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_017_002_redefinitionDeMethodes + Exe + ex_017_002_redefinitionDeMethodes + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_017_003_initialiseurs_constructeurs/Program.cs b/p03_POO/ex_017_003_initialiseurs_constructeurs/Program.cs new file mode 100644 index 0000000..99d7302 --- /dev/null +++ b/p03_POO/ex_017_003_initialiseurs_constructeurs/Program.cs @@ -0,0 +1,67 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_017_003_initialiseurs_constructeurs +{ + class UneClasse + { + public UneClasse(string info) + { + WriteLine($"appel du constructeur de UneClasse {info}"); + } + } + + class BaseClass + { + static UneClasse une_classe = new UneClasse("(depuis un membre statique de BaseClass) "); + + UneClasse une_classe2 = new UneClasse("(depuis un membre d'une instance de BaseClass) "); + + static BaseClass() + { + WriteLine("appel du constructeur statique de BaseClass"); + } + + public BaseClass() + { + WriteLine("appel du constructeur d'une instance de BaseClass"); + } + } + + class ChildClass : BaseClass + { + static UneClasse une_classe3 = new UneClasse(" (depuis un membre statique de ChildClass)"); + + UneClasse une_classe4 = new UneClasse(" (depuis un membre d'une instance de ChildClass) "); + + static ChildClass() + { + WriteLine("appel du constructeur statique de ChildClass"); + } + + public ChildClass() + { + WriteLine("appel du constructeur d'une instance de ChildClass"); + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + ChildClass c = new ChildClass(); + } + } +} diff --git a/p03_POO/ex_017_003_initialiseurs_constructeurs/ex_017_003_initialiseurs_constructeurs.csproj b/p03_POO/ex_017_003_initialiseurs_constructeurs/ex_017_003_initialiseurs_constructeurs.csproj new file mode 100644 index 0000000..a011777 --- /dev/null +++ b/p03_POO/ex_017_003_initialiseurs_constructeurs/ex_017_003_initialiseurs_constructeurs.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_017_003_initialiseurs_constructeurs + Exe + ex_017_003_initialiseurs_constructeurs + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_017_004_casting/Program.cs b/p03_POO/ex_017_004_casting/Program.cs new file mode 100644 index 0000000..506e19f --- /dev/null +++ b/p03_POO/ex_017_004_casting/Program.cs @@ -0,0 +1,88 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_017_004_casting +{ + class BaseClass + { + public string Affiche() + { + return "je suis une instance de BaseClass"; + } + } + + class ChildClass : BaseClass + { + public string Affiche() + { + return "je suis une instance de ChildClass"; + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //upcasting : implicite + WriteLine("Upcasting"); + ChildClass c = new ChildClass(); + WriteLine(c.Affiche()); + BaseClass b = c; + WriteLine(b.Affiche()); + WriteLine(); + + //downcasting (C-like) : explicite + WriteLine("Downcasting (C-like)"); + BaseClass b2 = new BaseClass(); + c = (ChildClass)b; //pas d'erreur + WriteLine(c.Affiche()); + try + { + c = (ChildClass)b2; // erreur, b2 n'est pas une ChildClass + WriteLine(c.Affiche()); + } + catch (Exception e) + { + WriteLine(e.Message); + } + WriteLine(); + + //downcasting en C# : explicite + WriteLine("Downcasting en C# avec is et as"); + WriteLine($"b is ChildClass ? {b is ChildClass}"); + WriteLine($"b2 is ChildClass ? {b2 is ChildClass}"); + + ChildClass c2 = b as ChildClass; + if (c2 != null) + { + WriteLine(c2.Affiche()); + } + else + { + WriteLine("c2 n'est pas de type ChildClass"); + } + c2 = b2 as ChildClass; + if (c2 != null) + { + WriteLine(c2.Affiche()); + } + else + { + WriteLine("c2 n'est pas de type ChildClass"); + } + } + } +} diff --git a/p03_POO/ex_017_004_casting/ex_017_004_casting.csproj b/p03_POO/ex_017_004_casting/ex_017_004_casting.csproj new file mode 100644 index 0000000..d1b16cd --- /dev/null +++ b/p03_POO/ex_017_004_casting/ex_017_004_casting.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_017_004_casting + Exe + ex_017_004_casting + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_018_001_polymorphisme/Program.cs b/p03_POO/ex_018_001_polymorphisme/Program.cs new file mode 100644 index 0000000..78e7005 --- /dev/null +++ b/p03_POO/ex_018_001_polymorphisme/Program.cs @@ -0,0 +1,157 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_018_001_polymorphisme +{ + //classe mère + class MediaObjet + { + public string Titre + { + get { return mTitre; } + } + protected string mTitre = "unknown"; + protected int mAnnéeCréation; + + public MediaObjet(string titre, int année) + { + mTitre = titre; + mAnnéeCréation = année; + } + + //notez que Affiche est maintenant virtuelle + public virtual void Affiche() + { + WriteLine($"Ce média s'intitule {mTitre} et a été créé en {mAnnéeCréation}"); + } + } + + //une classe fille + class Disque : MediaObjet + { + private string mArtiste = "unknown"; + + public Disque(string titre, int année, string artiste) + : base(titre, année) + { + mArtiste = artiste; + } + + //on précise qu'il s'agit bien de la méthode virtuelle de la classe mère avec le mot clé override + public override void Affiche() + { + WriteLine($"Le disque {mTitre} a été enregistré par {mArtiste} en {mAnnéeCréation}"); + //on peut aussi continuer à appeler la méthode Affiche de la classe mère à l'aide de base en décommentant la ligne suivante : + //base.Affiche(); + } + } + + //une autre classe fille + class Livre : MediaObjet + { + private string mAuteur; + + public Livre(string titre, int année, string auteur) + : base(titre, année) + { + mAuteur = auteur; + } + + //on précise qu'il s'agit bien de la méthode virtuelle de la classe mère avec le mot clé override + public override void Affiche() + { + WriteLine($"Le livre {mTitre} a été écrit par {mAuteur} en {mAnnéeCréation}"); + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //ici pas de pb : + + //l est de type Livre (construit avec Livre) et appelle Affiche de Livre + Livre l = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + l.Affiche(); + + //d est de type Disque (construit avec Disque) et appelle Affiche de Disque + Disque d = new Disque("Underground", 2007, "Chris Potter"); + d.Affiche(); + + //mo est de type MediaObjet (construit avec MediaObjet) et appelle Affiche de MediaObjet + MediaObjet mo = new MediaObjet("La Grande Vadrouille", 1966); + mo.Affiche(); + + //modifions un peu à présent : + + //mo1 est de type MediaObjet et construit avec le constructeur de MediaObjet, il appelle Affiche de MediaObjet + MediaObjet mo1 = new MediaObjet("La Grande Vadrouille", 1966); + mo1.Affiche(); + //mo2 est de type MediaObjet mais construit avec le constructeur de Livre, il appelle Affiche de Livre + MediaObjet mo2 = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + mo2.Affiche(); + //mo2 est de type MediaObjet mais construit avec le constructeur de Disque, il appelle Affiche de Disque + MediaObjet mo3 = new Disque("Underground", 2007, "Chris Potter"); + mo3.Affiche(); + //avec les méthodes virtuelles, lors de l'exécution, le véritable type est testé. + + //on peut toutefois continuer à appeler la méthode (dite maintenant cachée) de la classe mère 0 l'aide de base + //cf. commentaire dans la classe Disque + + + + //on peut aussi utiliser le mot clé "is" pour tester le type d'un objet + if (mo1 is Livre) + { + WriteLine($"{mo1.Titre} est un livre"); + } + else + { + WriteLine($"{mo1.Titre} n'est pas un livre"); + } + if (mo2 is Livre) + { + WriteLine($"{mo2.Titre} est un livre"); + } + else + { + WriteLine($"{mo2.Titre} n'est pas un livre"); + } + if (mo3 is Livre) + { + WriteLine($"{mo3.Titre} est un livre"); + } + else + { + WriteLine($"{mo3.Titre} n'est pas un livre"); + } + + + + //ou encore le mot clé as + Livre l2 = mo2 as Livre; + if (l2 != null) + l2.Affiche(); + else + WriteLine($"{mo2.Titre} n'est pas un livre"); + + Livre l3 = mo3 as Livre; + if (l3 != null) + l3.Affiche(); + else + WriteLine($"{mo3.Titre} n'est pas un livre"); + } + } +} diff --git a/p03_POO/ex_018_001_polymorphisme/ex_018_001_polymorphisme.csproj b/p03_POO/ex_018_001_polymorphisme/ex_018_001_polymorphisme.csproj new file mode 100644 index 0000000..35c4810 --- /dev/null +++ b/p03_POO/ex_018_001_polymorphisme/ex_018_001_polymorphisme.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_018_001_polymorphisme + Exe + ex_018_001_polymorphisme + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_018_002_abstract/Program.cs b/p03_POO/ex_018_002_abstract/Program.cs new file mode 100644 index 0000000..788b17b --- /dev/null +++ b/p03_POO/ex_018_002_abstract/Program.cs @@ -0,0 +1,146 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_018_002_abstract +{ + //classe mère abstraite + //notez le mot clé abstract + abstract class MediaObjet + { + public string Titre + { + get { return mTitre; } + } + protected string mTitre; + protected int mAnnéeCréation; + + public MediaObjet(string titre, int année) + { + mTitre = titre; + mAnnéeCréation = année; + } + + //notez que Affiche est maintenant abstraite : les classes filles, si elles veulent être concrètes, doivent l'implémenter + public abstract void Affiche(); + + } + + //une classe fille + class Disque : MediaObjet + { + private string mArtiste; + + public Disque(string titre, int année, string artiste) + : base(titre, année) + { + mArtiste = artiste; + } + + //on précise qu'il s'agit bien de la méthode abstraite de la classe mère abstraite avec le mot clé override + public override void Affiche() + { + WriteLine($"Le disque {mTitre} a été enregistré par {mArtiste} en {mAnnéeCréation}"); + } + } + + //une autre classe fille + class Livre : MediaObjet + { + private string mAuteur; + + public Livre(string titre, int année, string auteur) + : base(titre, année) + { + mAuteur = auteur; + } + + //on précise qu'il s'agit bien de la méthode abstraite de la classe mère abstraite avec le mot clé override + public override void Affiche() + { + WriteLine($"Le livre {mTitre} a été écrit par {mAuteur} en {mAnnéeCréation}"); + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //l est de type Livre (construit avec Livre) et appelle Affiche de Livre + Livre l = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + l.Affiche(); + + //d est de type Disque (construit avec Disque) et appelle Affiche de Disque + Disque d = new Disque("Underground", 2007, "Chris Potter"); + d.Affiche(); + + //on ne peut pas appeler le constructeur de MediaObjet car la classe est abstraite + //MediaObjet mo = new MediaObjet("La Grande Vadrouille", 1966); + //mo.Affiche(); + + //modifions un peu à présent : + + //on ne peut toujours pas appeler le constructeur de MediaObjet (classe abstraite) + //MediaObjet mo1 = new MediaObjet("La Grande Vadrouille", 1966); + //mo1.Affiche(); + //mo2 est de type MediaObjet mais construit avec le constructeur de Livre, il appelle Affiche de Livre + //même si mo2 est de type MediaObjet(classe abstraite), comme il a été construit avec une classe concrète (Livre), il n'y a pas d'erreurs + MediaObjet mo2 = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + mo2.Affiche(); + //mo2 est de type MediaObjet mais construit avec le constructeur de Disque, il appelle Affiche de Disque + MediaObjet mo3 = new Disque("Underground", 2007, "Chris Potter"); + mo3.Affiche(); + //avec les méthodes virtuelles, lors de l'exécution, le véritable type est testé. + + + + + //on peut aussi toujours le mot clé "is" pour tester le type d'un objet + //on peut aussi utiliser le mot clé "is" pour tester le type d'un objet + if (mo2 is Livre) + { + WriteLine($"{mo2.Titre} est un livre"); + } + else + { + WriteLine($"{mo2.Titre} n'est pas un livre"); + } + if (mo3 is Livre) + { + WriteLine($"{mo3.Titre} est un livre"); + } + else + { + WriteLine($"{mo3.Titre} n'est pas un livre"); + } + + + + + + //ou encore le mot clé as + Livre l2 = mo2 as Livre; + if (l2 != null) + l2.Affiche(); + else + WriteLine($"{mo2.Titre} n'est pas un livre"); + + Livre l3 = mo3 as Livre; + if (l3 != null) + l3.Affiche(); + else + WriteLine($"{mo3.Titre} n'est pas un livre"); + } + } +} diff --git a/p03_POO/ex_018_002_abstract/ex_018_002_abstract.csproj b/p03_POO/ex_018_002_abstract/ex_018_002_abstract.csproj new file mode 100644 index 0000000..26cb3ec --- /dev/null +++ b/p03_POO/ex_018_002_abstract/ex_018_002_abstract.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_018_002_abstract + Exe + ex_018_002_abstract + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_019_001_interfaces/Program.cs b/p03_POO/ex_019_001_interfaces/Program.cs new file mode 100644 index 0000000..8ca0937 --- /dev/null +++ b/p03_POO/ex_019_001_interfaces/Program.cs @@ -0,0 +1,190 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_019_001_interfaces +{ + //interface + //notez le mot clé interface + interface IMediaObjet + { + //une interface ne possède pas de champs et ses méthodes et propriétés ne sont pas implémentées + + //les méthodes, propriétés, indexeurs et événements ne donnent pas l'accessibilité (public, private, internal, protected) + //Cette accessibilité est implicitement publique. + //En conséquence, les classes implémentant l'interface devront obligatoirement implémenter les méthodes, propriétés, indexeurs et événements + //déclarés par l'interface comme publiques + void Affiche(); + + string Titre + { + get; + } + } + + interface IMusiqueObjet + { + string Producteur + { + get; + } + } + + + + //une classe fille + class Livre : IMediaObjet + { + protected string mTitre; + protected int mAnnéeCréation; + private string mAuteur; + + public Livre(string titre, int année, string auteur) + { + mTitre = titre; + mAnnéeCréation = année; + mAuteur = auteur; + } + + //pas besoin de préciser override + public void Affiche() + { + WriteLine($"Le livre {mTitre} a été écrit par {mAuteur} en {mAnnéeCréation}"); + } + + public string Titre + { + get + { + return mTitre; + } + } + } + + //on peut implémenter plusieurs interfaces + class Disque : IMediaObjet, IMusiqueObjet + { + private string mArtiste; + protected string mTitre; + protected int mAnnéeCréation; + private string mProducteur; + + public Disque(string titre, int année, string artiste, string producteur) + { + mTitre = titre; + mAnnéeCréation = année; + mArtiste = artiste; + mProducteur = producteur; + } + + //pas besoin de préciser override + public void Affiche() + { + WriteLine($"Le disque {mTitre} a été enregistré par {mArtiste} en {mAnnéeCréation}, et produit par {mProducteur}"); + } + + public string Titre + { + get + { + return mTitre; + } + private set + { + mTitre = value; + } + } + + public string Producteur + { + get + { + return mProducteur; + } + } + + } + + //les structures aussi peuvent implémenter des interfaces + struct Film : IMediaObjet + { + string mTitre; + + public Film(string titre) + { + mTitre = titre; + } + + public string Titre + { + get + { + return mTitre; + } + } + public void Affiche() + { + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + //l est de type Livre (construit avec Livre) et appelle Affiche de Livre + Livre l = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + l.Affiche(); + + //d est de type Disque (construit avec Disque) et appelle Affiche de Disque + Disque d = new Disque("Tommy", 1969, "The Who", "Kit Lambert"); + d.Affiche(); + + //on ne peut pas appeler le constructeur de IMediaObjet car c'est une interface + //IMediaObjet mo = new IMediaObjet(); + //mo.Affiche(); + + //mo2 implémente IMediaObjet et est construit avec le constructeur de Livre, il appelle Affiche de Livre + //même si mo2 est de type IMediaObjet(interface), comme il a été construit avec une classe concrète (Livre), il n'y a pas d'erreurs + IMediaObjet mo2 = new Livre("Attenti al Gorilla", 1995, "Sandrone Dazieri"); + mo2.Affiche(); + //mo3 implémente IMediaObjet et est construit avec le constructeur de Disque, il appelle Affiche de Disque + //même si mo3 est de type IMediaObjet(interface), comme il a été construit avec une classe concrète (Disque), il n'y a pas d'erreurs + IMediaObjet mo3 = new Disque("Tommy", 1969, "The Who", "Kit Lambert"); + mo3.Affiche(); + //avec les méthodes virtuelles, lors de l'exécution, le véritable type est testé. + + + + + //on peut aussi vérifier avec is ou as qu'un objet implémente une interface + if (l is IMusiqueObjet) + { + WriteLine($"{l.Titre} implémente l'interface IMusiqueObjet"); + } + else + { + WriteLine($"{l.Titre} n'implémente pas l'interface"); + } + if (d is IMusiqueObjet) + { + WriteLine($"{d.Titre} implémente l'interface IMusiqueObjet"); + } + else + { + WriteLine($"{d.Titre} n'implémente pas l'interface"); + } + + } + } +} diff --git a/p03_POO/ex_019_001_interfaces/ex_019_001_interfaces.csproj b/p03_POO/ex_019_001_interfaces/ex_019_001_interfaces.csproj new file mode 100644 index 0000000..7422f2c --- /dev/null +++ b/p03_POO/ex_019_001_interfaces/ex_019_001_interfaces.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_019_001_interfaces + Exe + ex_019_001_interfaces + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_020_001_structures/Program.cs b/p03_POO/ex_020_001_structures/Program.cs new file mode 100644 index 0000000..59a44c0 --- /dev/null +++ b/p03_POO/ex_020_001_structures/Program.cs @@ -0,0 +1,114 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_020_001_structures +{ + /// + /// présentation rapide des structures en C# : + /// - les variables structurées sont de type "valeur" (allouées en mémoire sur la pile, plus rapide que sur le tas, mais moins de place) + /// - pas d'héritage possible (à part d'object (implicite) et System.ValueType) + /// - pas de constructeur par défaut et pas d'initialiseur dans la définition des champs. + /// - pas de membres, propriétés ou méthodes virtuelles + /// + struct StructDisque + { + public string Titre { get; set; } + + public int Année { get; set; } + + public StructDisque(string titre, int année) + { + Titre = titre; + Année = année; + } + } + + class ClassDisque + { + public string Titre { get; set; } + + public int Année { get; set; } + + public ClassDisque(string titre, int année) + { + Titre = titre; + Année = année; + } + } + + /// + /// utilisation d'une structure + /// + class Program + { + static void Main(string[] args) + { + { + WriteLine("Avec des structures :"); + StructDisque sd1 = new StructDisque("Voice In The Night", 1999); + int year = sd1.Année; + string title = sd1.Titre; + WriteLine($"sd1 : {sd1.Titre} ({sd1.Année})"); + WriteLine(); + + StructDisque sd2 = new StructDisque("The Water Is Wide", 2000); + year = sd2.Année; + title = sd2.Titre; + WriteLine($"sd2 : {sd2.Titre} ({sd2.Année})"); + WriteLine(); + + sd2 = sd1; + WriteLine("sd2 = sd1;"); + WriteLine($"sd1 : {sd1.Titre} ({sd1.Année})"); + WriteLine($"sd2 : {sd2.Titre} ({sd2.Année})"); + WriteLine(); + + WriteLine("modification de sd1"); + sd1.Titre = "Hyperion With Higgins"; + sd1.Année = 2001; + WriteLine($"sd1 : {sd1.Titre} ({sd1.Année})"); + WriteLine($"sd2 : {sd2.Titre} ({sd2.Année})"); + WriteLine(); + } + + { + WriteLine("Avec des classes :"); + ClassDisque cd1 = new ClassDisque("Voice In The Night", 1999); + int year = cd1.Année; + string title = cd1.Titre; + WriteLine($"cd1 : {cd1.Titre} ({cd1.Année})"); + WriteLine(); + + ClassDisque cd2 = new ClassDisque("The Water Is Wide", 2000); + year = cd2.Année; + title = cd2.Titre; + WriteLine($"cd2 : {cd2.Titre} ({cd2.Année})"); + WriteLine(); + + cd2 = cd1; + WriteLine("cd2 = cd1;"); + WriteLine($"cd1 : {cd1.Titre} ({cd1.Année})"); + WriteLine($"cd2 : {cd2.Titre} ({cd2.Année})"); + WriteLine(); + + WriteLine("modification de cd1"); + cd1.Titre = "Hyperion With Higgins"; + cd1.Année = 2001; + cd1 = new ClassDisque("Hyperion With Higgins", 2001); + WriteLine($"cd1 : {cd1.Titre} ({cd1.Année})"); + WriteLine($"cd2 : {cd2.Titre} ({cd2.Année})"); + WriteLine(); + } + } + } +} diff --git a/p03_POO/ex_020_001_structures/ex_020_001_structures.csproj b/p03_POO/ex_020_001_structures/ex_020_001_structures.csproj new file mode 100644 index 0000000..6f57f76 --- /dev/null +++ b/p03_POO/ex_020_001_structures/ex_020_001_structures.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_020_001_structures + Exe + ex_020_001_structures + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_021_001_patternComposite/Program.cs b/p03_POO/ex_021_001_patternComposite/Program.cs new file mode 100644 index 0000000..dc1afd3 --- /dev/null +++ b/p03_POO/ex_021_001_patternComposite/Program.cs @@ -0,0 +1,101 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; +using System.Collections.Generic; +using static ex_021_001_patternComposite.Component; + +namespace ex_021_001_patternComposite +{ + interface IComponent + { + string Nom { get; set; } + + void Operation(string tab); + } + + class Component : IComponent + { + internal const string TAB = " "; + + public string Nom + { + get; + set; + } + + public void Operation(string tab = TAB) + { + WriteLine($"{tab}Je suis {Nom}, un {GetType().Name}, et je réalise mon opération"); + } + } + + class Composite : IComponent + { + public string Nom + { + get; + set; + } + + List mChildren = new List(); + + public void AddRange(params IComponent[] children) + { + mChildren.AddRange(children); + } + + public void Operation(string tab = TAB) + { + WriteLine($"{tab}Je suis {Nom}, un {GetType().Name}, et je débute mon opération"); + WriteLine($"{tab}Je suis {Nom}, un {GetType().Name}, et je fais travailler mes enfants"); + foreach (IComponent child in mChildren) + { + child.Operation(tab + TAB); + } + WriteLine($"{tab}Je suis {Nom}, un {GetType().Name}, et j'ai terminé mon opération"); + } + } + + class Program + { + //N6 ---> N5 ---> N4 --> N1 + // | | + // | --> N2 + // | + // --> N3 + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Component noeud1 = new Component() { Nom = "Noeud1" }; + Component noeud2 = new Component() { Nom = "Noeud2" }; + Component noeud3 = new Component() { Nom = "Noeud3" }; + Composite noeud4 = new Composite() { Nom = "Noeud4" }; + Composite noeud5 = new Composite() { Nom = "Noeud5" }; + Composite noeud6 = new Composite() { Nom = "Noeud6" }; + noeud6.AddRange(noeud5, noeud3); + noeud5.AddRange(noeud4, noeud2); + noeud4.AddRange(noeud1); + + noeud1.Operation(); + ReadLine(); + Clear(); + noeud4.Operation(); + ReadLine(); + Clear(); + noeud5.Operation(); + ReadLine(); + Clear(); + noeud6.Operation(); + } + } +} diff --git a/p03_POO/ex_021_001_patternComposite/ex_021_001_patternComposite.csproj b/p03_POO/ex_021_001_patternComposite/ex_021_001_patternComposite.csproj new file mode 100644 index 0000000..667cff3 --- /dev/null +++ b/p03_POO/ex_021_001_patternComposite/ex_021_001_patternComposite.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_021_001_patternComposite + Exe + ex_021_001_patternComposite + 6.0.6 + false + false + false + + diff --git a/p03_POO/ex_021_002_patternStrategy/Program.cs b/p03_POO/ex_021_002_patternStrategy/Program.cs new file mode 100644 index 0000000..ab9d369 --- /dev/null +++ b/p03_POO/ex_021_002_patternStrategy/Program.cs @@ -0,0 +1,56 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-26 +// +// ======================================================================== + +using static System.Console; + +namespace ex_021_002_patternStrategy +{ + interface IStrategy + { + void Operation(); + } + + class StrategyA : IStrategy + { + public void Operation() + { + WriteLine("Je fais le travail demandé en faisant \"wouf wouf\""); + } + } + + class StrategyB : IStrategy + { + public void Operation() + { + WriteLine("Je fais le travail demandé en faisant \"miaou miaou\""); + } + } + + class Program + { + static IStrategy maStrategie; + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + WriteLine("J'utilise la stratégie A pour faire le travail"); + + maStrategie = new StrategyA(); + maStrategie.Operation(); + + WriteLine("J'utilise la stratégie B pour faire le travail"); + + maStrategie = new StrategyB(); + maStrategie.Operation(); + } + } +} diff --git a/p03_POO/ex_021_002_patternStrategy/ex_021_002_patternStrategy.csproj b/p03_POO/ex_021_002_patternStrategy/ex_021_002_patternStrategy.csproj new file mode 100644 index 0000000..5eada57 --- /dev/null +++ b/p03_POO/ex_021_002_patternStrategy/ex_021_002_patternStrategy.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_021_002_patternStrategy + Exe + ex_021_002_patternStrategy + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_001_Generics_def_du_pb/Program.cs b/p04_AdvancedCSharp/ex_022_001_Generics_def_du_pb/Program.cs new file mode 100644 index 0000000..ccf330b --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_001_Generics_def_du_pb/Program.cs @@ -0,0 +1,183 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_022_001_Generics_def_du_pb +{ + /// + /// Définition du problème : + /// - on construit un tableau d'entiers à taille variable + /// - on construit ensuite le même tableau, mais de nounours + /// - à chaque fois, on refait une classe, seulement pour contenir d'autres types... + /// c'est pénible... + /// + class Program + { + /// + /// 1er exemple : un tableau d'entiers + /// + public class IntArray + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + int mSize = 0; + + /// + /// tableau d'entiers + /// + int[] mData = new int[0]; + + /// + /// ajoute un entier à la fin du tableau + /// + /// entier à rajouter + public void Push(int entier) + { + mSize++; + int[] data = new int[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = entier; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + public int this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + throw new IndexOutOfRangeException(); + } + return mData[index]; + } + } + } + + + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + IntArray tab_int = new IntArray(); + tab_int.Push(10); + tab_int.Push(20); + tab_int.Push(30); + tab_int.Push(40); + tab_int.Push(50); + WriteLine("début de tab_int"); + for (int i = 0; i < tab_int.Size; i++) + { + WriteLine(tab_int[i]); + } + WriteLine("fin\n"); + + NounoursArray tab_nounours = new NounoursArray(); + tab_nounours.Push(new Nounours("Hello Kitty")); + tab_nounours.Push(new Nounours("Pokemon")); + tab_nounours.Push(new Nounours("Pokoyo")); + tab_nounours.Push(new Nounours("Tigrou")); + tab_nounours.Push(new Nounours("PussInBoots")); + WriteLine("début de tab_nounours"); + for (int i = 0; i < tab_int.Size; i++) + { + WriteLine(tab_nounours[i].Nom); + } + WriteLine("fin\n"); + } + + /// + /// class Nounours + /// + public class Nounours + { + /// + /// constructeur + /// + /// nom du nounours + public Nounours(string nom) + { + Nom = nom; + } + + /// + /// nom du nounours + /// + public string Nom + { + get; + private set; + } + } + + /// + /// un tableau de nounours + /// + public class NounoursArray + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + int mSize = 0; + + /// + /// tableau de nounours + /// + Nounours[] mData = new Nounours[0]; + + /// + /// ajoute un nounours à la fin du tableau + /// + /// nounours à rajouter + public void Push(Nounours nounours) + { + mSize++; + Nounours[] data = new Nounours[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = nounours; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + public Nounours this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + throw new IndexOutOfRangeException(); + } + return mData[index]; + } + } + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_001_Generics_def_du_pb/ex_022_001_Generics_def_du_pb.csproj b/p04_AdvancedCSharp/ex_022_001_Generics_def_du_pb/ex_022_001_Generics_def_du_pb.csproj new file mode 100644 index 0000000..f07405c --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_001_Generics_def_du_pb/ex_022_001_Generics_def_du_pb.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_001_Generics_def_du_pb + Exe + ex_022_001_Generics_def_du_pb + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_002_Generics_EtPourquoiPasObject/Program.cs b/p04_AdvancedCSharp/ex_022_002_Generics_EtPourquoiPasObject/Program.cs new file mode 100644 index 0000000..14ff913 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_002_Generics_EtPourquoiPasObject/Program.cs @@ -0,0 +1,128 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_022_002_Generics_EtPourquoiPasObject +{ + /// + /// première solution (mauvaise) : faire un tableau d'Object + /// + class Program + { + /// + /// un tableau d'objet (donc n'importe quoi) + /// + public class ObjectArray + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + int mSize = 0; + + /// + /// tableau d'object + /// + object[] mData = new object[0]; + + /// + /// ajoute un objet à la fin du tableau + /// + /// objet à rajouter + public void Push(object objet) + { + mSize++; + object[] data = new object[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = objet; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + public object this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + throw new IndexOutOfRangeException(); + } + return mData[index]; + } + } + } + + /// + /// class Nounours + /// + public class Nounours + { + /// + /// constructeur + /// + /// nom du nounours + public Nounours(string nom) + { + Nom = nom; + } + + /// + /// nom du nounours + /// + public string Nom + { + get; + private set; + } + } + + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + ObjectArray tab_int = new ObjectArray(); + tab_int.Push(10); + tab_int.Push(20); + tab_int.Push(30); + tab_int.Push(40); + tab_int.Push(50); + WriteLine("début de tab_int"); + for (int i = 0; i < tab_int.Size; i++) + { + WriteLine(tab_int[i]); + } + WriteLine("fin\n"); + + ObjectArray tab_nounours = new ObjectArray(); + tab_nounours.Push(new Nounours("Hello Kitty")); + tab_nounours.Push(new Nounours("Pokemon")); + tab_nounours.Push(new Nounours("Pokoyo")); + tab_nounours.Push(new Nounours("Tigrou")); + tab_nounours.Push(new Nounours("PussInBoots")); + WriteLine("début de tab_nounours"); + for (int i = 0; i < tab_int.Size; i++) + { + WriteLine((tab_nounours[i] as Nounours).Nom); // il faut caster ! + } + WriteLine("fin\n"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_002_Generics_EtPourquoiPasObject/ex_022_002_Generics_EtPourquoiPasObject.csproj b/p04_AdvancedCSharp/ex_022_002_Generics_EtPourquoiPasObject/ex_022_002_Generics_EtPourquoiPasObject.csproj new file mode 100644 index 0000000..6a19a96 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_002_Generics_EtPourquoiPasObject/ex_022_002_Generics_EtPourquoiPasObject.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_002_Generics_EtPourquoiPasObject + Exe + ex_022_002_Generics_EtPourquoiPasObject + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_003_Generics_syntaxe/Program.cs b/p04_AdvancedCSharp/ex_022_003_Generics_syntaxe/Program.cs new file mode 100644 index 0000000..d677838 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_003_Generics_syntaxe/Program.cs @@ -0,0 +1,119 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_022_003_Generics_syntaxe +{ + /// + /// C# propose 2 façons d'écrire du code "réutilisable" à travers des types différents : + /// l'utilisation de l'héritage ou l'utilisation du la généricité. + /// L'héritage propose la réutilisabilité à travers un type de base, alors que la généricité + /// se base sur un "patron" (template). + /// + class Program + { + /// + /// 1er exemple : un tableau de "choses" (inconnues à l'avance) + /// + /// choses contenues par le tableau + public class Tableau + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + int mSize = 0; + + /// + /// tableau d'object + /// + T[] mData = new T[0]; + + /// + /// ajoute un objet à la fin du tableau + /// + /// objet à rajouter + public void Push(T objet) + { + mSize++; + T[] data = new T[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = objet; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + public T this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + throw new IndexOutOfRangeException(); + } + return mData[index]; + } + } + } + + public class Nounours + { + public Nounours(string nom) + { + Nom = nom; + } + + public string Nom + { + get; + private set; + } + } + + static void Main(string[] args) + { + //un tableau d'entiers + Tableau tab_int = new Tableau(); + tab_int.Push(10); + tab_int.Push(20); + tab_int.Push(30); + tab_int.Push(40); + tab_int.Push(50); + for (int i = 0; i < tab_int.Size; i++) + { + WriteLine(tab_int[i]); + } + WriteLine("fin\n"); + + //un tableau de nounours + Tableau tab_nounours = new Tableau(); + tab_nounours.Push(new Nounours("Hello Kitty")); + tab_nounours.Push(new Nounours("Pokemon")); + tab_nounours.Push(new Nounours("Pokoyo")); + tab_nounours.Push(new Nounours("Tigrou")); + tab_nounours.Push(new Nounours("PussInBoots")); + for (int i = 0; i < tab_nounours.Size; i++) + { + WriteLine(tab_nounours[i].Nom); + } + WriteLine("fin\n"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_003_Generics_syntaxe/ex_022_003_Generics_syntaxe.csproj b/p04_AdvancedCSharp/ex_022_003_Generics_syntaxe/ex_022_003_Generics_syntaxe.csproj new file mode 100644 index 0000000..c732d58 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_003_Generics_syntaxe/ex_022_003_Generics_syntaxe.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_003_Generics_syntaxe + Exe + ex_022_003_Generics_syntaxe + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_004_Generics_default/Program.cs b/p04_AdvancedCSharp/ex_022_004_Generics_default/Program.cs new file mode 100644 index 0000000..6186b3c --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_004_Generics_default/Program.cs @@ -0,0 +1,115 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using static System.Console; + +namespace ex_022_004_Generics_default +{ + /// + /// exemple montrant l'utilisation du mot clé default (cf. indexer) + /// + class Program + { + /// + /// 1er exemple : un tableau de "choses" (inconnues à l'avance) + /// + /// choses contenues par le tableau + public class Tableau + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + int mSize = 0; + + /// + /// tableau d'object + /// + T[] mData = new T[0]; + + /// + /// ajoute un objet à la fin du tableau + /// + /// objet à rajouter + public void Push(T objet) + { + mSize++; + T[] data = new T[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = objet; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + public T this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + return default(T); // <<<<----------------- utilisation du mot clé default : rend la valeur par défaut du type + // e.g. 0 pour int, null pour Nounours (reference) + } + return mData[index]; + } + } + } + + public class Nounours + { + public Nounours(string nom) + { + Nom = nom; + } + + public string Nom + { + get; + private set; + } + } + + static void Main(string[] args) + { + Tableau tab_int = new Tableau(); + tab_int.Push(10); + tab_int.Push(20); + tab_int.Push(30); + tab_int.Push(40); + tab_int.Push(50); + for (int i = 0; i < tab_int.Size + 1; i++) + { + WriteLine(tab_int[i]); + } + WriteLine("fin\n"); + + Tableau tab_nounours = new Tableau(); + tab_nounours.Push(new Nounours("Hello Kitty")); + tab_nounours.Push(new Nounours("Pokemon")); + tab_nounours.Push(new Nounours("Pokoyo")); + tab_nounours.Push(new Nounours("Tigrou")); + tab_nounours.Push(new Nounours("PussInBoots")); + for (int i = 0; i < tab_nounours.Size + 1; i++) + { + if (tab_nounours[i] != null) + WriteLine(tab_nounours[i].Nom); + } + WriteLine("fin\n"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_004_Generics_default/ex_022_004_Generics_default.csproj b/p04_AdvancedCSharp/ex_022_004_Generics_default/ex_022_004_Generics_default.csproj new file mode 100644 index 0000000..8d4bad0 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_004_Generics_default/ex_022_004_Generics_default.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_004_Generics_default + Exe + ex_022_004_Generics_default + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_005_Generics_constraints/Program.cs b/p04_AdvancedCSharp/ex_022_005_Generics_constraints/Program.cs new file mode 100644 index 0000000..bf51cf5 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_005_Generics_constraints/Program.cs @@ -0,0 +1,123 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2014-03-30 +// +// ======================================================================== + +using static System.Console; + +namespace ex_022_005_Generics_constraints +{ + /// + /// exemple montrant l'utilisation d'une contrainte : le paramètre T DOIT avoir un constructeur par défaut + /// + class Program + { + /// + /// 1er exemple : un tableau de "choses" (inconnues à l'avance) + /// + /// choses contenues par le tableau + public class Tableau where T : new() //<<<<<-------------------------contrainte : un constructeur par défaut + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + int mSize = 0; + + /// + /// tableau d'object + /// + T[] mData = new T[0]; + + /// + /// ajoute un objet à la fin du tableau + /// + /// objet à rajouter + public void Push(T objet) + { + mSize++; + T[] data = new T[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = objet; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + public T this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + return new T(); //on peut utiliser new T() car T doit avoir un constructeur par défaut + } + return mData[index]; + } + } + } + + public class Nounours + { + /// + /// constructeur par défaut, ok pour être utilisé dans Tableau<> + /// + public Nounours() + { + Nom = "délaissé..."; + } + + public Nounours(string nom) + { + Nom = nom; + } + + public string Nom + { + get; + private set; + } + } + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Tableau tab_int = new Tableau(); + tab_int.Push(10); + tab_int.Push(20); + tab_int.Push(30); + tab_int.Push(40); + tab_int.Push(50); + for (int i = 0; i < tab_int.Size + 1; i++) + { + WriteLine(tab_int[i]); + } + WriteLine("fin\n"); + + Tableau tab_nounours = new Tableau(); + tab_nounours.Push(new Nounours("Hello Kitty")); + tab_nounours.Push(new Nounours("Pokemon")); + tab_nounours.Push(new Nounours("Pokoyo")); + tab_nounours.Push(new Nounours("Tigrou")); + tab_nounours.Push(new Nounours("PussInBoots")); + for (int i = 0; i < tab_nounours.Size + 1; i++) + { + WriteLine(tab_nounours[i].Nom); + } + WriteLine("fin\n"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_005_Generics_constraints/ex_022_005_Generics_constraints.csproj b/p04_AdvancedCSharp/ex_022_005_Generics_constraints/ex_022_005_Generics_constraints.csproj new file mode 100644 index 0000000..ebb291b --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_005_Generics_constraints/ex_022_005_Generics_constraints.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_005_Generics_constraints + Exe + ex_022_005_Generics_constraints + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_006_Generics_constraints2/Program.cs b/p04_AdvancedCSharp/ex_022_006_Generics_constraints2/Program.cs new file mode 100644 index 0000000..2446918 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_006_Generics_constraints2/Program.cs @@ -0,0 +1,131 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_022_006_Generics_constraints2 +{ + /// + /// exemple d'utilisation de contraintes : T DOIT dériver de la classe Animal + /// + class Program + { + /// + /// 1er exemple : un tableau de "choses" (inconnues à l'avance) + /// + /// choses contenues par le tableau + public class Tableau where T : Animal + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + int mSize = 0; + + /// + /// tableau d'object + /// + T[] mData = new T[0]; + + /// + /// ajoute un objet à la fin du tableau + /// + /// objet à rajouter + public void Push(T objet) + { + mSize++; + T[] data = new T[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = objet; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + public T this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + throw new IndexOutOfRangeException(); + } + return mData[index]; + } + } + } + + public class Animal + { + public string Type + { + get; + protected set; + } + } + + /// + /// ne dérive pas d'Animal + /// + public class Caillou + { + } + + /// + /// dérive d'Animal + /// + public class Oiseau : Animal + { + public Oiseau(string nom, string famille) + { + Type = "Tétrapode"; + Nom = nom; + Famille = famille; + } + + public string Nom + { + get; + private set; + } + + public string Famille + { + get; + private set; + } + } + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Tableau tab_oiseaux = new Tableau(); + tab_oiseaux.Push(new Oiseau("canard à bosse", "anatidés")); + tab_oiseaux.Push(new Oiseau("faucon aplomado", "falconidés")); + tab_oiseaux.Push(new Oiseau("effraie des clochers", "tytonidés")); + for (int i = 0; i < tab_oiseaux.Size; i++) + { + WriteLine($"{tab_oiseaux[i].Nom} (famille : {tab_oiseaux[i].Famille} - type : {tab_oiseaux[i].Type})"); + } + WriteLine("fin\n"); + + //Tableau tab_caillou = new Tableau(); + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_006_Generics_constraints2/ex_022_006_Generics_constraints2.csproj b/p04_AdvancedCSharp/ex_022_006_Generics_constraints2/ex_022_006_Generics_constraints2.csproj new file mode 100644 index 0000000..0b3d487 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_006_Generics_constraints2/ex_022_006_Generics_constraints2.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_006_Generics_constraints2 + Exe + ex_022_006_Generics_constraints2 + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_007_Generics_subclassing/Program.cs b/p04_AdvancedCSharp/ex_022_007_Generics_subclassing/Program.cs new file mode 100644 index 0000000..087aa5c --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_007_Generics_subclassing/Program.cs @@ -0,0 +1,197 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_022_007_Generics_subclassing +{ + /// + /// Généricité et dérivation + /// + class Program + { + /// + /// 1er exemple : un tableau de "choses" (inconnues à l'avance) + /// + /// choses contenues par le tableau + public class Tableau + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + protected int mSize = 0; + + /// + /// tableau d'object + /// + protected T[] mData = new T[0]; + + /// + /// ajoute un objet à la fin du tableau + /// + /// objet à rajouter + virtual public void Push(T objet) + { + mSize++; + T[] data = new T[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = objet; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + virtual public T this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + throw new IndexOutOfRangeException(); + } + return mData[index]; + } + } + } + + /// + /// dérivation qui laisse le type générique ouvert + /// + /// + public class SuperTableau : Tableau where T : new() + { + public T Pop() + { + if (Size > 0) + { + mSize--; + return mData[Size]; + + } + else + { + return new T(); + } + } + } + + /// + /// dérivation fermant le type générique avec un type concret + /// + public class TableauInt : Tableau + { + public override int this[int index] + { + get + { + if (index < 0 || index >= Size) + { + return 0; + } + return mData[index]; + } + } + } + + /// + /// dérivation ouvrant un nouveau type générique + /// + /// + /// + public class TableauDouble : Tableau where U : new() + { + U[] mData2 = new U[0]; + + public override void Push(T objet) + { + Push(objet); + U[] data = new U[Size]; + mData2.CopyTo(data, 0); + data[Size - 1] = new U(); + mData2 = data; + } + + public void Push(T obj1, U obj2) + { + base.Push(obj1); + U[] data = new U[Size]; + mData2.CopyTo(data, 0); + data[Size - 1] = obj2; + mData2 = data; + } + + public U GetU(int index) + { + if (index < 0 || index >= mSize) + { + throw new IndexOutOfRangeException(); + } + return mData2[index]; + } + + } + + static void Main(string[] args) + { + Tableau tab_int = new Tableau(); + tab_int.Push(1); + tab_int.Push(2); + tab_int.Push(3); + for (int i = 0; i < tab_int.Size; i++) + { + WriteLine(i); + } + WriteLine("fin"); + WriteLine(); + + SuperTableau sup_tab = new SuperTableau(); + sup_tab.Push(7); + sup_tab.Push(8); + sup_tab.Push(9); + while (sup_tab.Size > 0) + { + WriteLine(sup_tab.Pop()); + } + WriteLine("fin"); + WriteLine(); + + TableauInt tab_int2 = new TableauInt(); + tab_int2.Push(4); + tab_int2.Push(5); + tab_int2.Push(6); + for (int i = 0; i < tab_int2.Size; i++) + { + WriteLine(tab_int2[i]); + } + WriteLine("fin"); + WriteLine(); + + TableauDouble tab3 = new TableauDouble(); + tab3.Push(11, 1.1f); + tab3.Push(12, 1.2f); + tab3.Push(13, 1.3f); + for (int i = 0; i < tab3.Size; i++) + { + WriteLine($"{tab3[i]} {tab3.GetU(i)}"); + } + + + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_007_Generics_subclassing/ex_022_007_Generics_subclassing.csproj b/p04_AdvancedCSharp/ex_022_007_Generics_subclassing/ex_022_007_Generics_subclassing.csproj new file mode 100644 index 0000000..329a201 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_007_Generics_subclassing/ex_022_007_Generics_subclassing.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_007_Generics_subclassing + Exe + ex_022_007_Generics_subclassing + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_008_CovarianceClasses/Program.cs b/p04_AdvancedCSharp/ex_022_008_CovarianceClasses/Program.cs new file mode 100644 index 0000000..4450ff9 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_008_CovarianceClasses/Program.cs @@ -0,0 +1,149 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_022_008_CovarianceClasses +{ + /// + /// Généricité et covariance + /// + class Program + { + /// + /// 1er exemple : un tableau de "choses" (inconnues à l'avance) + /// + /// choses contenues par le tableau + public class Tableau where T : Animal + { + /// + /// taille du tableau + /// + public int Size + { + get { return mSize; } + } + int mSize = 0; + + /// + /// tableau d'object + /// + T[] mData = new T[0]; + + /// + /// ajoute un objet à la fin du tableau + /// + /// objet à rajouter + public void Push(T objet) + { + mSize++; + T[] data = new T[mSize]; + mData.CopyTo(data, 0); + data[mSize - 1] = objet; + mData = data; + } + + /// + /// indexer en lecture seule pour lire les éléments du tableau + /// + /// index dans le tableau + /// la valeur à cet index + public T this[int index] + { + get + { + if (index < 0 || index >= mSize) + { + throw new IndexOutOfRangeException(); + } + return mData[index]; + } + } + } + + public class Animal + { + public string Type + { + get; + protected set; + } + } + + /// + /// dérive d'Animal + /// + public class Oiseau : Animal + { + public Oiseau(string nom, string famille) + { + Type = "Tétrapode"; + Nom = nom; + Famille = famille; + } + + public string Nom + { + get; + private set; + } + + public string Famille + { + get; + private set; + } + } + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Tableau tab_oiseaux = new Tableau(); + tab_oiseaux.Push(new Oiseau("canard à bosse", "anatidés")); + tab_oiseaux.Push(new Oiseau("faucon aplomado", "falconidés")); + tab_oiseaux.Push(new Oiseau("effraie des clochers", "tytonidés")); + + //on ne peut pas caster un Tableau en Tableau, même si on peut caster un Oiseau en Animal + Animal animal = tab_oiseaux[0]; //<-- autorisé + //Tableau tab_animaux = tab_oiseaux; //<-- erreur de compilation + for (int i = 0; i < tab_oiseaux.Size; i++) + { + WriteLine($"{tab_oiseaux[i].Nom} (famille : {tab_oiseaux[i].Famille} - type : {tab_oiseaux[i].Type})"); + } + WriteLine("fin\n"); + + Sauver2(tab_oiseaux); + } + + //UNE SOLUTION... + + /// + /// une méthode qui ne marche pas... + /// + /// + static void Sauver(Tableau animaux) + { + WriteLine("on rentre bien dans Sauver"); + } + + /// + /// une méthode qui marche + /// + /// + /// + static void Sauver2(Tableau animaux) where T : Animal + { + WriteLine("on rentre bien dans Sauver2"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_008_CovarianceClasses/ex_022_008_CovarianceClasses.csproj b/p04_AdvancedCSharp/ex_022_008_CovarianceClasses/ex_022_008_CovarianceClasses.csproj new file mode 100644 index 0000000..96fb595 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_008_CovarianceClasses/ex_022_008_CovarianceClasses.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_008_CovarianceClasses + Exe + ex_022_008_CovarianceClasses + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_022_009_CovarianceInterfaces/Program.cs b/p04_AdvancedCSharp/ex_022_009_CovarianceInterfaces/Program.cs new file mode 100644 index 0000000..77640c6 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_009_CovarianceInterfaces/Program.cs @@ -0,0 +1,46 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_022_009_CovarianceInterfaces +{ + interface BaseInterface + { + } + + class BaseClass : BaseInterface + { + } + + class ChildClass : BaseClass + { + } + + class Program + { + static void Main(string[] args) + { + IEnumerable collec_child_class = new List(); + //autorisé car les interfaces sont covariantes + IEnumerable collec_base_class = collec_child_class; + + List list_child_class = new List(); + //non autorisé car les classes ne sont pas covariantes + //List list_base_class = list_child_class; + + //autorisé car List implémente IEnumerable et IEnumerable<> est covariante + collec_base_class = list_child_class; + //autorisé + IEnumerable collec_base_interface = list_child_class; + } + } +} diff --git a/p04_AdvancedCSharp/ex_022_009_CovarianceInterfaces/ex_022_009_CovarianceInterfaces.csproj b/p04_AdvancedCSharp/ex_022_009_CovarianceInterfaces/ex_022_009_CovarianceInterfaces.csproj new file mode 100644 index 0000000..a13c170 --- /dev/null +++ b/p04_AdvancedCSharp/ex_022_009_CovarianceInterfaces/ex_022_009_CovarianceInterfaces.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_022_009_CovarianceInterfaces + Exe + ex_022_009_CovarianceInterfaces + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_001_IEnumerator_ex1/Program.cs b/p04_AdvancedCSharp/ex_023_001_IEnumerator_ex1/Program.cs new file mode 100644 index 0000000..253dba9 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_001_IEnumerator_ex1/Program.cs @@ -0,0 +1,46 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-27 +// +// ======================================================================== + +using static System.Console; +using System.Collections.Generic; + +namespace ex_023_001_IEnumerator_ex1 +{ + class Program + { + static void Main(string[] args) + { + int[] tab = { 1, 2, 3 }; + System.Collections.IEnumerator etor = tab.GetEnumerator(); + + while (etor.MoveNext()) + { + int a = (int)etor.Current; + WriteLine(a); + } + + WriteLine("ou"); + + foreach (int a in tab) + { + WriteLine(a); + } + + //2ème exemple + string s = "Bonjour"; + System.Collections.IEnumerator str_etor = (s as IEnumerable).GetEnumerator(); + while (str_etor.MoveNext()) + { + Write($"{str_etor.Current}."); + } + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_001_IEnumerator_ex1/ex_023_001_IEnumerator_ex1.csproj b/p04_AdvancedCSharp/ex_023_001_IEnumerator_ex1/ex_023_001_IEnumerator_ex1.csproj new file mode 100644 index 0000000..eb0b8f3 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_001_IEnumerator_ex1/ex_023_001_IEnumerator_ex1.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_001_IEnumerator_ex1 + Exe + ex_023_001_IEnumerator_ex1 + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/Program.cs b/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/Program.cs new file mode 100644 index 0000000..3abd883 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/Program.cs @@ -0,0 +1,27 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-28 +// +// ======================================================================== + +using static System.Console; + +namespace ex_023_002_IEnumerator_ex2 +{ + class Program + { + static void Main(string[] args) + { + StrangeCollection col = new StrangeCollection(); + foreach (int i in col) + { + WriteLine(i); + } + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/StrangeCollection.cs b/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/StrangeCollection.cs new file mode 100644 index 0000000..1f54005 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/StrangeCollection.cs @@ -0,0 +1,36 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : StrangeCollection.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-28 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_023_002_IEnumerator_ex2 +{ + class StrangeCollection : IEnumerable + { + int[] data = { 1, 2, 3, 4, 5, 6 }; + + public IEnumerator GetEnumerator() + { + foreach (int i in data) + { + if (i % 2 == 0) + { + yield return i; + } + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/ex_023_002_IEnumerator_ex2.csproj b/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/ex_023_002_IEnumerator_ex2.csproj new file mode 100644 index 0000000..c1f3d2c --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_002_IEnumerator_ex2/ex_023_002_IEnumerator_ex2.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_002_IEnumerator_ex2 + Exe + ex_023_002_IEnumerator_ex2 + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/Program.cs b/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/Program.cs new file mode 100644 index 0000000..431f3b5 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/Program.cs @@ -0,0 +1,27 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-28 +// +// ======================================================================== + +using static System.Console; + +namespace ex_023_003_IEnumerator_ex3 +{ + class Program + { + static void Main(string[] args) + { + StrangeCollection col = new StrangeCollection(); + foreach (int i in col) + { + WriteLine(i); + } + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/StrangeCollection.cs b/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/StrangeCollection.cs new file mode 100644 index 0000000..d568cc1 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/StrangeCollection.cs @@ -0,0 +1,74 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : StrangeCollection.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-28 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_023_003_IEnumerator_ex3 +{ + class StrangeCollection : IEnumerable + { + int[] data = { 1, 2, 3, 4, 5, 6 }; + + public IEnumerator GetEnumerator() + { + return new StrangeEnumerator(this); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return new StrangeEnumerator(this); + } + + class StrangeEnumerator : IEnumerator + { + int mCurrentIndex = -1; + StrangeCollection mCollection; + + internal StrangeEnumerator(StrangeCollection collection) + { + mCollection = collection; + } + + public int Current + { + get + { + return mCollection.data[mCurrentIndex]; + } + } + object System.Collections.IEnumerator.Current + { + get + { + return Current; + } + } + + public bool MoveNext() + { + mCurrentIndex++; + while (mCurrentIndex < mCollection.data.Length && mCollection.data[mCurrentIndex] % 2 != 0) + { + mCurrentIndex++; + } + return mCurrentIndex < mCollection.data.Length; + } + + public void Reset() + { + mCurrentIndex = -1; + } + + void IDisposable.Dispose() { } + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/ex_023_003_IEnumerator_ex3.csproj b/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/ex_023_003_IEnumerator_ex3.csproj new file mode 100644 index 0000000..336cfbc --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_003_IEnumerator_ex3/ex_023_003_IEnumerator_ex3.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_003_IEnumerator_ex3 + Exe + ex_023_003_IEnumerator_ex3 + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_004_ArrayClass/Program.cs b/p04_AdvancedCSharp/ex_023_004_ArrayClass/Program.cs new file mode 100644 index 0000000..44de9e6 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_004_ArrayClass/Program.cs @@ -0,0 +1,114 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-28 +// +// ======================================================================== + +using System; +using System.Text; +using static System.Console; + +namespace ex_023_004_ArrayClass +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + StringBuilder[] data = new StringBuilder[4]; + data[0] = new StringBuilder("sb1"); + data[1] = new StringBuilder("sb2"); + data[2] = new StringBuilder("sb3"); + + //Copie, attention aux références ! + StringBuilder[] data2 = data; //data et data2 pointent sur les mêmes cases mémoire ! + StringBuilder[] data3 = (StringBuilder[])data.Clone(); //la ième case de data et la ième case de data3 contiennent les mêmes références + + //Length, Rank, GetLength + int[,,] tab = { { {1, 2, 3}, {4, 5, 6} }, + { {7, 8, 9}, {0, 1, 2} }, + { {3, 4, 5}, {6, 7, 8} }, + { {9, 0, 1}, {2, 3, 4} } }; + WriteLine($"Length: {tab.Length}"); + WriteLine($"Rank: {tab.Rank}"); + WriteLine($"GetLength(0): {tab.GetLength(0)}"); + WriteLine($"GetLength(1): {tab.GetLength(1)}"); + WriteLine($"GetLength(2): {tab.GetLength(2)}"); + + //Sort + WriteLine("Sort"); + int[] nombres = { 3, 2, 1 }; + foreach (int i in nombres) Write($"{i} "); + WriteLine(); + Array.Sort(nombres); + foreach (int i in nombres) Write($"{i} "); + WriteLine(); + + //on peut aussi trier deux tableaux en tandem : le premier est trié et les éléments du second prennent les mêmes positions + int[] nombres2 = { 3, 2, 1 }; + string[] nombres3 = { "trois", "deux", "un" }; + WriteLine("tandem Sort"); + foreach (int i in nombres2) Write($"{i} "); + WriteLine(); + foreach (string s in nombres3) Write($"{s} "); + WriteLine(); + Array.Sort(nombres2, nombres3); + foreach (int i in nombres2) Write($"{i} "); + WriteLine(); + foreach (string s in nombres3) Write($"{s} "); + WriteLine(); + + //inverser les éléments + WriteLine("Reverse"); + int[] nombres4 = { 1, 2, 3, 4, 5, 6 }; + foreach (int i in nombres4) Write($"{i} "); + WriteLine(); + Array.Reverse(nombres4); + foreach (int i in nombres4) Write($"{i} "); + WriteLine(); + + //Read only + System.Collections.ObjectModel.ReadOnlyCollection nombres5 = new System.Collections.ObjectModel.ReadOnlyCollection(nombres4); + foreach (int i in nombres5) Write($"{i} "); + WriteLine(); + //nombres5[0] += 10; //erreur de compilation + + //faire des recherches + int lookedElement = 2; + Write($"l'élément {lookedElement} se trouve à la position "); + WriteLine($"{Array.IndexOf(nombres4, lookedElement)} dans le tableau nombres4"); + WriteLine(); + + Write("Le premier élément du tableau nombres3 à contenir un 'u' est "); + ForegroundColor = ConsoleColor.Red; + WriteLine(Array.Find(nombres3, n => n.Contains("u"))); + ForegroundColor = ConsoleColor.White; + WriteLine(); + + Write("Les éléments du tableau nombres3 qui contiennent un 'u' sont "); + ForegroundColor = ConsoleColor.Red; + foreach (string s in Array.FindAll(nombres3, n => n.Contains("u"))) + { + Write($"{s} "); + } + ForegroundColor = ConsoleColor.White; + WriteLine(); + WriteLine(); + + string àchercher = "deux"; + Write($"existe-t-il un élément nommé {àchercher} dans le tableau nombres3 ? {Array.Exists(nombres3, n => n.Equals(àchercher))}"); + WriteLine(); + + àchercher = "quatre"; + Write($"existe-t-il un élément nommé {àchercher} dans le tableau nombres3 ? {Array.Exists(nombres3, n => n.Equals(àchercher))}"); + WriteLine(); + + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_004_ArrayClass/ex_023_004_ArrayClass.csproj b/p04_AdvancedCSharp/ex_023_004_ArrayClass/ex_023_004_ArrayClass.csproj new file mode 100644 index 0000000..29551cc --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_004_ArrayClass/ex_023_004_ArrayClass.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_004_ArrayClass + Exe + ex_023_004_ArrayClass + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_005_Queue/Program.cs b/p04_AdvancedCSharp/ex_023_005_Queue/Program.cs new file mode 100644 index 0000000..0adba17 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_005_Queue/Program.cs @@ -0,0 +1,51 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-28 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using static System.Console; + +namespace ex_023_005_Queue +{ + class Program + { + static void Main(string[] args) + { + Queue queue = new Queue(); + queue.Enqueue("client 1"); + queue.Enqueue("client 2"); + queue.Enqueue("client 3"); + queue.Enqueue("client 4"); + WriteLine("ToArray"); + string[] tab = queue.ToArray(); + foreach (string s in tab) WriteLine(s); + + WriteLine("Count"); + WriteLine(queue.Count); + WriteLine("Peek"); // prend le prochain élément qui sortira, sans le sortir + WriteLine(queue.Peek()); + WriteLine("Dequeue"); // sort le prochain élément et le rend + WriteLine(queue.Dequeue()); + WriteLine(queue.Dequeue()); + WriteLine(queue.Dequeue()); + WriteLine(queue.Dequeue()); + try + { + WriteLine(queue.Dequeue()); //exception + } + catch (Exception e) + { + WriteLine(e); + } + } + + } +} diff --git a/p04_AdvancedCSharp/ex_023_005_Queue/ex_023_005_Queue.csproj b/p04_AdvancedCSharp/ex_023_005_Queue/ex_023_005_Queue.csproj new file mode 100644 index 0000000..2a9f353 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_005_Queue/ex_023_005_Queue.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_005_Queue + Exe + ex_023_005_Queue + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_006_Stack/Program.cs b/p04_AdvancedCSharp/ex_023_006_Stack/Program.cs new file mode 100644 index 0000000..841a9bf --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_006_Stack/Program.cs @@ -0,0 +1,49 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-28 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using static System.Console; + +namespace ex_023_006_Stack +{ + class Program + { + static void Display(Stack stack) + { + Write("stack :"); + foreach (int i in stack) Write($"{i} "); + WriteLine(); + } + + static void Main(string[] args) + { + Stack stack = new Stack(); + stack.Push(1); Display(stack); + stack.Push(2); Display(stack); + stack.Push(3); Display(stack); + WriteLine(stack.Count); + WriteLine(stack.Peek()); Display(stack); + WriteLine(stack.Pop()); Display(stack); + WriteLine(stack.Pop()); Display(stack); + WriteLine(stack.Pop()); Display(stack); + + try + { + WriteLine(stack.Pop()); Display(stack); + } + catch (Exception e) + { + WriteLine(e); + } + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_006_Stack/ex_023_006_Stack.csproj b/p04_AdvancedCSharp/ex_023_006_Stack/ex_023_006_Stack.csproj new file mode 100644 index 0000000..c5e2b45 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_006_Stack/ex_023_006_Stack.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_006_Stack + Exe + ex_023_006_Stack + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_007_LinkedList/Program.cs b/p04_AdvancedCSharp/ex_023_007_LinkedList/Program.cs new file mode 100644 index 0000000..268803a --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_007_LinkedList/Program.cs @@ -0,0 +1,60 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2014-03-30 +// Mise à jour : 2016-09-28 +// +// ======================================================================== + +using static System.Console; +using System.Collections.Generic; + +namespace ex_023_007_LinkedList +{ + class Program + { + static void Display(LinkedList notes) + { + WriteLine("début"); + foreach (string s in notes) + { + Write($"{s} "); + } + WriteLine(); + WriteLine("fin"); + } + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + LinkedList notes = new LinkedList(); + + WriteLine("AddFirst, AddLast"); + notes.AddFirst("do"); + notes.AddLast("sol"); + Display(notes); + + WriteLine("AddAfter, AddBefore, First, Next, Last"); + notes.AddAfter(notes.First, "re"); + notes.AddAfter(notes.First.Next, "mi"); + notes.AddBefore(notes.Last, "fa"); + Display(notes); + + WriteLine("RemoveFirst, RemoveLast"); + notes.RemoveFirst(); + notes.RemoveLast(); + Display(notes); + + WriteLine("manipulation de nodes"); + LinkedListNode mi = notes.Find("mi"); + notes.Remove(mi); + notes.AddFirst(mi); + Display(notes); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_007_LinkedList/ex_023_007_LinkedList.csproj b/p04_AdvancedCSharp/ex_023_007_LinkedList/ex_023_007_LinkedList.csproj new file mode 100644 index 0000000..562ad62 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_007_LinkedList/ex_023_007_LinkedList.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_007_LinkedList + Exe + ex_023_007_LinkedList + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_008_List/Program.cs b/p04_AdvancedCSharp/ex_023_008_List/Program.cs new file mode 100644 index 0000000..2c52167 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_008_List/Program.cs @@ -0,0 +1,89 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-28 +// +// ======================================================================== + +using static System.Console; +using System.Collections.Generic; + +namespace ex_023_008_List +{ + class Program + { + static void Display(List colors) + { + WriteLine("début"); + foreach (string s in colors) + { + WriteLine($"\t{s}"); + } + WriteLine("fin"); + } + + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + List colors = new List(); + WriteLine("Add"); + colors.Add("rouge"); + colors.Add("jaune"); + Display(colors); + + WriteLine("AddRange"); + colors.AddRange(new string[] { "vert", "bleu", "orange" }); + Display(colors); + + WriteLine("Insert"); + colors.Insert(1, "violet"); + Display(colors); + + WriteLine("InsertRange"); + colors.InsertRange(3, new string[] { "beige", "gris", "noir", "rose" }); + Display(colors); + + WriteLine("Remove"); + colors.Remove("bleu"); + colors.RemoveAt(2); + colors.RemoveRange(3, 2); + Display(colors); + + WriteLine("RemoveAll string starting with v"); + colors.RemoveAll(delegate (string s) { return s.StartsWith("v"); }); + Display(colors); + + WriteLine("indexer et Count"); + WriteLine(colors[0]); + WriteLine(colors[colors.Count - 1]); + + WriteLine("subsets"); + Display(colors.GetRange(1, 2)); + + WriteLine("ToArray"); + string[] tab = colors.ToArray(); + foreach (string s in tab) WriteLine($"{s} "); + WriteLine(); + + WriteLine("CopyTo"); + colors.CopyTo(2, tab, 0, 2); //copie, à partir du 3 ème élément de colors, dans tab à partir du 1er élément, 2 éléments. + foreach (string s in tab) WriteLine($"{s} "); + WriteLine(); + + //searching and sorting + WriteLine("Dans Colors, les éléments suivants commencent par 'r' : "); + foreach (string s in colors.FindAll(n => n.StartsWith("r"))) + { + WriteLine($"{s} "); + } + WriteLine(); + } + + + } +} diff --git a/p04_AdvancedCSharp/ex_023_008_List/ex_023_008_List.csproj b/p04_AdvancedCSharp/ex_023_008_List/ex_023_008_List.csproj new file mode 100644 index 0000000..ffa8f83 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_008_List/ex_023_008_List.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_008_List + Exe + ex_023_008_List + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_009_HashSet_and_SortedSet/Program.cs b/p04_AdvancedCSharp/ex_023_009_HashSet_and_SortedSet/Program.cs new file mode 100644 index 0000000..44af41e --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_009_HashSet_and_SortedSet/Program.cs @@ -0,0 +1,105 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-10 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using static System.Console; + +namespace ex_023_009_HashSet_and_SortedSet +{ + /// + /// HashSet et SortedSet sont deux collections génériques introduites respectivement en .NET 3.5 et .NET 4.0. + /// Les caractéristiques de ces collections sont : + /// - elles sont très efficaces pour la recherche d'éléments (Contains utilise une méthode de hashage) + /// - elles ne stockent pas de doublons + /// - on ne peut pas les utiliser avec un indexeur + /// De plus, SortedSet ordonne les éléments. + /// HashSet utilise une hashtable, SortedSet un red/black tree. + /// Les deux collections implémentent ICollection et ISet + /// + class Program + { + static void Display(ISet colors) + { + WriteLine("début"); + foreach (string s in colors) + { + WriteLine($"\t{s}"); + } + WriteLine("fin"); + } + + static void Main(string[] args) + { + HashSet colorsHashSet = new HashSet(new string[] { "vert", "rouge", "bleu", "orange" }); + SortedSet colorsSortedSet = new SortedSet(new string[] { "vert", "rouge", "bleu", "orange" }); + WriteLine("Add"); + colorsHashSet.Add("rouge"); + colorsHashSet.Add("jaune"); + Display(colorsHashSet); + + colorsSortedSet.Add("rouge"); + colorsSortedSet.Add("jaune"); + Display(colorsSortedSet); + + + // Set Operations (destructive methods) + List colorsList = new List { "rose", "mauve", "noir", "bleu", "jaune" }; + WriteLine("UnionWith"); + colorsHashSet.UnionWith(colorsList); //colorsHashSet est modifié (des éléments sont ajoutés) + Display(colorsHashSet); + WriteLine("IntersectWith"); //colorsSortedSet est modifié (des éléments sont enlevés) + colorsSortedSet.IntersectWith(colorsList); + Display(colorsSortedSet); + colorsHashSet = new HashSet(new string[] { "vert", "rouge", "bleu", "orange", "jaune" }); + colorsSortedSet = new SortedSet(new string[] { "vert", "rouge", "bleu", "orange", "jaune" }); + WriteLine("ExceptWith"); //enlève les élements qui sont dans les deux + colorsHashSet.ExceptWith(colorsList); //colorsHashSet est modifié (des éléments sont enlevés + Display(colorsHashSet); + WriteLine("SymmetricExceptWith"); // ne garde que les éléments qui ne sont qu'une seule fois dans l'une ou l'autre des deux collections + colorsSortedSet.SymmetricExceptWith(colorsList); //colorsSortedSet est modifié (des éléments sont enlevés + Display(colorsSortedSet); + + // Query methods (non-destructive methods) + colorsHashSet = new HashSet(new string[] { "vert", "bleu", "jaune" }); + colorsSortedSet = new SortedSet(new string[] { "vert", "rouge", "mauve", "bleu", "rose", "orange", "jaune", "noir" }); + List colorsList2 = new List { "vert", "rouge", "bleu", "orange", "jaune" }; + WriteLine("IsSubsetOf"); //est-ce un sous-ensemble de ... + WriteLine($"colorsHashSet.IsSubsetOf(colorsList2) ? {colorsHashSet.IsSubsetOf(colorsList2)}"); + WriteLine("IsSupersetOf"); //est-ce un sur-ensemble de ... + WriteLine($"colorsSortedSet.IsSupersetOf(colorsList2) ? {colorsSortedSet.IsSupersetOf(colorsList2)}"); + WriteLine("Overlaps"); //y a-t-il des éléments en commun avec ... + WriteLine($"colorsHashSet.Overlaps(colorsList2) ? {colorsHashSet.Overlaps(colorsList2)}"); + WriteLine("SetEquals"); //ont-ils exactement les mêmes éléments + WriteLine($"colorsHashSet.SetEquals(colorsList2) ? {colorsHashSet.SetEquals(colorsList2)}"); + + //méthodes propres à SortedSet + //un SortedSet peut prendre un IComparer dans son constructeur + SortedSet colorsSortedSet2 = new SortedSet(StringComparer.CurrentCultureIgnoreCase); + //un SortedSet peut sortir un sous-ensemble donné entre deux valeurs (inf et sup) + WriteLine("GetViewBetween"); //y a-t-il des éléments en commun avec ... + var colorsViewBetweenSortedSet = colorsSortedSet.GetViewBetween("l", "q"); + Display(colorsViewBetweenSortedSet); + //on peut aussi inverser, obtenir le min et le max + WriteLine("Min, Max"); //y a-t-il des éléments en commun avec ... + WriteLine($"Min : {colorsSortedSet.Min}"); + WriteLine($"Max : {colorsSortedSet.Max}"); + + WriteLine("Reverse"); //y a-t-il des éléments en commun avec ... + WriteLine("début"); + foreach (string s in colorsSortedSet.Reverse()) + { + WriteLine($"\t{s}"); + } + WriteLine("fin"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_009_HashSet_and_SortedSet/ex_023_009_HashSet_and_SortedSet.csproj b/p04_AdvancedCSharp/ex_023_009_HashSet_and_SortedSet/ex_023_009_HashSet_and_SortedSet.csproj new file mode 100644 index 0000000..5b83b24 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_009_HashSet_and_SortedSet/ex_023_009_HashSet_and_SortedSet.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_009_HashSet_and_SortedSet + Exe + ex_023_009_HashSet_and_SortedSet + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/Nounours.cs b/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/Nounours.cs new file mode 100644 index 0000000..ab73e31 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/Nounours.cs @@ -0,0 +1,83 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; + +namespace ex_023_010_EqualityProtocoleOnReferences +{ + class Nounours : IEquatable + { + public int Id + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public Nounours(int id, string name) + { + Id = id; + Name = name; + } + + //... + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Id % 31; + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Id == other.Id); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/Program.cs b/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/Program.cs new file mode 100644 index 0000000..9146d35 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/Program.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using static System.Console; + +namespace ex_023_010_EqualityProtocoleOnReferences +{ + class Program + { + static void Main(string[] args) + { + VieuxNounours grouinf = new VieuxNounours(1, "grouinf"); + VieuxNounours grouinf2 = new VieuxNounours(1, "grouinf"); + WriteLine($"grouinf == grouinf2 ? {grouinf == grouinf2}"); + WriteLine($"grouinf.Equals(grouinf2) ? {grouinf.Equals(grouinf2)}"); + + Nounours grouinf3 = new Nounours(1, "grouinf3"); + Nounours grouinf4 = new Nounours(1, "grouinf4"); + WriteLine($"grouinf3 == grouinf4 ? {grouinf3 == grouinf4}"); + WriteLine($"grouinf3.Equals(grouinf4) ? {grouinf3.Equals(grouinf4)}"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/VieuxNounours.cs b/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/VieuxNounours.cs new file mode 100644 index 0000000..0183f44 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/VieuxNounours.cs @@ -0,0 +1,36 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : VieuxNounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +namespace ex_023_010_EqualityProtocoleOnReferences +{ + class VieuxNounours + { + public int Id + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public VieuxNounours(int id, string name) + { + Id = id; + Name = name; + } + + //... + } +} diff --git a/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/ex_023_010_EqualityProtocoleOnReferences.csproj b/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/ex_023_010_EqualityProtocoleOnReferences.csproj new file mode 100644 index 0000000..bc315b2 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_010_EqualityProtocoleOnReferences/ex_023_010_EqualityProtocoleOnReferences.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_010_EqualityProtocoleOnReferences + Exe + ex_023_010_EqualityProtocoleOnReferences + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/Nounours.cs b/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/Nounours.cs new file mode 100644 index 0000000..0394d94 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/Nounours.cs @@ -0,0 +1,84 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2014-03-30 +// Mise à jour : 2016-09-29 +// +// ======================================================================== + +using System; + +namespace ex_023_011_EqualityProtocoleOnValues +{ + struct Nounours : IEquatable + { + public int Id + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public Nounours(int id, string name) + { + Id = id; + Name = name; + } + + //... + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Id % 31; + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + if (!(right is Nounours)) + { + return false; + } + return Equals((Nounours)right); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Id == other.Id); + } + + public static bool operator ==(Nounours nounours1, Nounours nounours2) + { + return nounours1.Equals(nounours2); + } + + public static bool operator !=(Nounours nounours1, Nounours nounours2) + { + return !nounours1.Equals(nounours2); + } + + + } +} diff --git a/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/Program.cs b/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/Program.cs new file mode 100644 index 0000000..67a80bf --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/Program.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using static System.Console; + +namespace ex_023_011_EqualityProtocoleOnValues +{ + class Program + { + static void Main(string[] args) + { + VieuxNounours grouinf = new VieuxNounours(1, "grouinf"); + VieuxNounours grouinf2 = new VieuxNounours(1, "grouinf2"); + //WriteLine("grouinf == grouinf2 ? " + (grouinf == grouinf2)); + WriteLine($"grouinf.Equals(grouinf2) ? {grouinf.Equals(grouinf2)}"); + + Nounours grouinf3 = new Nounours(1, "grouinf3"); + Nounours grouinf4 = new Nounours(1, "grouinf4"); + WriteLine($"grouinf3 == grouinf4 ? {grouinf3 == grouinf4}"); + WriteLine($"grouinf3.Equals(grouinf4) ? {grouinf3.Equals(grouinf4)}"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/VieuxNounours.cs b/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/VieuxNounours.cs new file mode 100644 index 0000000..2ee563a --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/VieuxNounours.cs @@ -0,0 +1,36 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : VieuxNounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +namespace ex_023_011_EqualityProtocoleOnValues +{ + struct VieuxNounours + { + public int Id + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public VieuxNounours(int id, string name) + { + Id = id; + Name = name; + } + + //... + } +} diff --git a/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/ex_023_011_EqualityProtocoleOnValues.csproj b/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/ex_023_011_EqualityProtocoleOnValues.csproj new file mode 100644 index 0000000..4308698 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_011_EqualityProtocoleOnValues/ex_023_011_EqualityProtocoleOnValues.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_026.0.6_EqualityProtocoleOnValues + Exe + ex_026.0.6_EqualityProtocoleOnValues + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Nounours.EqualityComparer.cs b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Nounours.EqualityComparer.cs new file mode 100644 index 0000000..0bfa713 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Nounours.EqualityComparer.cs @@ -0,0 +1,48 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.EqualityComparer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_023_012_EqualityComparer +{ + /// + /// Très bien quand on veut un deuxième equality comparer qui n'est pas celui par défaut, et qu'on a accès au code source de la classe + /// + partial class Nounours + { + private class DateDeNaissanceEqualityComparer : EqualityComparer + { + public override bool Equals(Nounours x, Nounours y) + { + return x.DateDeNaissance == y.DateDeNaissance; + } + + public override int GetHashCode(Nounours obj) + { + return (int)(obj.DateDeNaissance.Ticks % Int32.MaxValue); + } + } + + public static IEqualityComparer DateDeNaissanceEqualityCompare + { + get + { + if (mDateDeNaissanceEqualityCompare == null) + { + mDateDeNaissanceEqualityCompare = new DateDeNaissanceEqualityComparer(); + } + return mDateDeNaissanceEqualityCompare; + } + } + private static DateDeNaissanceEqualityComparer mDateDeNaissanceEqualityCompare = null; + } +} diff --git a/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Nounours.cs b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Nounours.cs new file mode 100644 index 0000000..f47bc2f --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Nounours.cs @@ -0,0 +1,97 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; + +namespace ex_023_012_EqualityComparer +{ + partial class Nounours : IEquatable + { + public int Id + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public Nounours(int id, string name, DateTime dateDeNaissance, int nbPoils) + { + Id = id; + Name = name; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + } + + //... + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Id % 31; + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Id == other.Id); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_012_EqualityComparer/NounoursNbPoilsEqualityComparer.cs b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/NounoursNbPoilsEqualityComparer.cs new file mode 100644 index 0000000..c5af59d --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/NounoursNbPoilsEqualityComparer.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.NbPoilsEqualityComparer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_023_012_EqualityComparer +{ + /// + /// Lorsqu'on n'a pas accès au code source de la classe, on doit passer par un equality comparer externe comme celui-ci + /// + class NounoursNbPoilsEqualityComparer : EqualityComparer + { + public override bool Equals(Nounours x, Nounours y) + { + return x.NbPoils == y.NbPoils; + } + + public override int GetHashCode(Nounours obj) + { + return obj.NbPoils; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Program.cs b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Program.cs new file mode 100644 index 0000000..6848a96 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/Program.cs @@ -0,0 +1,30 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_023_012_EqualityComparer +{ + class Program + { + static void Main(string[] args) + { + Nounours chucky1 = new Nounours(1, "chucky 1", new DateTime(1988, 11, 9), 150); + Nounours chucky2 = new Nounours(2, "chucky 2", new DateTime(1988, 11, 9), 125); + Nounours chucky3 = new Nounours(3, "chucky 3", new DateTime(1992, 11, 9), 125); + WriteLine($"chucky 1 == chucky 2 ? {chucky1 == chucky2}"); + WriteLine($"chucky1.Equals(chucky2) ? {chucky1.Equals(chucky2)}"); + WriteLine($"Nounours.DateDeNaissanceEqualityCompare.Equals(chucky1, chucky2) ? {Nounours.DateDeNaissanceEqualityCompare.Equals(chucky1, chucky2)}"); + WriteLine($"new NounoursNbPoilsEqualityComparer().Equals(chucky2, chucky3) ? {new NounoursNbPoilsEqualityComparer().Equals(chucky2, chucky3)}"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_012_EqualityComparer/ex_023_012_EqualityComparer.csproj b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/ex_023_012_EqualityComparer.csproj new file mode 100644 index 0000000..409d534 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_012_EqualityComparer/ex_023_012_EqualityComparer.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_012_EqualityComparer + Exe + ex_023_012_EqualityComparer + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Nounours.NbPoilsComparer.cs b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Nounours.NbPoilsComparer.cs new file mode 100644 index 0000000..83760d4 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Nounours.NbPoilsComparer.cs @@ -0,0 +1,43 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.NbPoilsComparer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_023_013_OrderComparisonProtocole +{ + /// + /// Si on a besoin d'un autre compareur et qu'on a accès au code source, on peut ajouter un IComparer générique statique à la classe + /// + partial class Nounours : IComparable, IComparable + { + private class NbPoilsComparer : IComparer + { + int IComparer.Compare(Nounours left, Nounours right) + { + return left.NbPoils.CompareTo(right.NbPoils); + } + } + + public static IComparer NbPoilsCompare + { + get + { + if (nbPoilsCompare == null) + { + nbPoilsCompare = new NbPoilsComparer(); + } + return nbPoilsCompare; + } + } + private static NbPoilsComparer nbPoilsCompare = null; + } +} diff --git a/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Nounours.cs b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Nounours.cs new file mode 100644 index 0000000..e06bbf0 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Nounours.cs @@ -0,0 +1,98 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; + +namespace ex_023_013_OrderComparisonProtocole +{ + /// + /// On implémente le compareur par défaut en implémentant IComparable + /// + partial class Nounours : IComparable, IComparable + { + public int Id + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public float Taille + { + get; + private set; + } + + public Nounours(int id, string name, DateTime dateDeNaissance, int nbPoils, float taille) + { + Id = id; + Name = name; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + Taille = taille; + } + + //... + + + public int CompareTo(Nounours other) + { + return Taille.CompareTo(other.Taille); + } + + int IComparable.CompareTo(object obj) + { + if (!(obj is Nounours)) + { + throw new ArgumentException("Argument is not a Nounours", "obj"); + } + Nounours otherNounours = obj as Nounours; + return this.CompareTo(otherNounours); + } + + public static bool operator <(Nounours left, Nounours right) + { + return left.CompareTo(right) < 0; + } + + public static bool operator <=(Nounours left, Nounours right) + { + return left.CompareTo(right) <= 0; + } + + public static bool operator >(Nounours left, Nounours right) + { + return left.CompareTo(right) > 0; + } + + public static bool operator >=(Nounours left, Nounours right) + { + return left.CompareTo(right) >= 0; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/NounoursDateComparer.cs b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/NounoursDateComparer.cs new file mode 100644 index 0000000..215e42c --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/NounoursDateComparer.cs @@ -0,0 +1,26 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursDateComparer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_023_013_OrderComparisonProtocole +{ + /// + /// Si on a besoin d'un autre compareur et qu'on n'a pas accès au code source, alors on utilise un IComparer générique externe + /// + class NounoursDateComparer : IComparer + { + public int Compare(Nounours x, Nounours y) + { + return x.DateDeNaissance.CompareTo(y.DateDeNaissance); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Program.cs b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Program.cs new file mode 100644 index 0000000..2413220 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/Program.cs @@ -0,0 +1,53 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_023_013_OrderComparisonProtocole +{ + class Program + { + static void Main(string[] args) + { + + Nounours[] monLit = { new Nounours(1, "Beluga", new DateTime(2012, 07, 29), 0, 35f), + new Nounours(2, "Singe", new DateTime(2009, 08, 09), 1345, 15f), + new Nounours(3, "Girafe", new DateTime(2007, 11, 02), 567, 215f)}; + foreach (Nounours n in monLit) + { + WriteLine(n.Name); + } + WriteLine("*****************"); + + Array.Sort(monLit); + foreach (Nounours n in monLit) + { + WriteLine(n.Name); + } + WriteLine("*****************"); + + Array.Sort(monLit, Nounours.NbPoilsCompare); + foreach (Nounours n in monLit) + { + WriteLine(n.Name); + } + WriteLine("*****************"); + + Array.Sort(monLit, new NounoursDateComparer()); + foreach (Nounours n in monLit) + { + WriteLine(n.Name); + } + WriteLine("*****************"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/ex_023_013_OrderComparisonProtocole.csproj b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/ex_023_013_OrderComparisonProtocole.csproj new file mode 100644 index 0000000..7bd095c --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_013_OrderComparisonProtocole/ex_023_013_OrderComparisonProtocole.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_013_OrderComparisonProtocole + Exe + ex_023_013_OrderComparisonProtocole + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_014_Dictionary/Program.cs b/p04_AdvancedCSharp/ex_023_014_Dictionary/Program.cs new file mode 100644 index 0000000..670d3dc --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_014_Dictionary/Program.cs @@ -0,0 +1,169 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using static System.Console; +using System.Collections.Generic; +using System.Text; +using System.Collections.Specialized; +using System.Collections; + +namespace ex_023_014_Dictionary +{ + /// + /// le dictionnaire est la collection la plus utilisée en .NET avec la List + /// Il utilise une structure de données en hashtable (d'ailleurs la version non générique du dictionnaire est HashTable). + /// Il stocke des pairs clé-valeur. + /// Il est rapide et efficace. + /// + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + //déclaration d'un dictionnaire + var dico = new Dictionary(); + + //on peut aussi déclarer le dictionnaire avec des valeurs directement : + dico = new Dictionary + { + {"Michael", 1 }, + {"Dwight", 0 }, + {"Angela", 1}, + {"Pam", 2 } + }; + + //et depuis C#6, on peut également initialiser le dictionnaire avec des valeurs avec la notation suivante : + dico = new Dictionary + { + ["Michael"] = 1, + ["Dwight"] = 0, + ["Angela"] = 1, + ["Pam"] = 2 + }; + + dico = new Dictionary(); + + //pour ajouter des paires clé-valeur, on peut utiliser la méthode Add, ou bien l'indexeur TValue this[TKey] + dico.Add("Romain", 1); //ajoute un nouveau couple "Romain", 1 + dico["Simon"] = 2; //ajoute un nouveau couple "Simon", 2 + dico["Guillaume"] = 2; //ajoute un nouveau couple "Guillaume", 2 + + //si la paire clé-valeur existe déjà, l'indexeur permet de modifier la valeur + dico["Guillaume"] = 3; //modifie la valeur du couple dont la clé est "Guillaume" en 3 + + //l'indexeur est utilisable en écriture et en lecture + dico["Romain"]++; //modifie la valeur du couple dont la clé est "Romain" en 2 + + WriteLine($"valeur de 'Romain' : {dico["Romain"]}"); + WriteLine($"valeur de 'Simon' : {dico["Simon"]}"); + WriteLine($"valeur de 'Guillaume' : {dico["Guillaume"]}"); + + //les méthodes ContainsKey et ContainsValue permettent de rechercher une clé en particulier ou une valeur en particulier + WriteLine($"le dico contient-il une clé 'Simon' ? {dico.ContainsKey("Simon")}"); + WriteLine($"le dico contient-il une valeur '2' ? {dico.ContainsValue(2)}"); + + //TryGetValue : sert à tester si la clé existe, et si c'est le cas, rend la valeur associée dans le paramètre out + int val; + if (!dico.TryGetValue("Simon", out val)) + { + WriteLine("pas de Simon"); + } + else + { + WriteLine($"Simon existe {val} fois"); + } + + if (!dico.TryGetValue("Gertrude", out val)) + { + WriteLine("pas de Gertrude"); + } + else + { + WriteLine("Gertrude existe"); + } + + //enumeration + //même si cela ne cherche pas à grand chose, on peut énumérer toutes les paires clé-valeur d'un dictionnaire avec foreach + // chaque élément est de type KeyValuePair + WriteLine("***********************"); + foreach (KeyValuePair pair in dico) + { + WriteLine($"{pair.Key} {pair.Value}"); + } + WriteLine("***********************"); + + //Keys permet d'obtenir toutes les clés en une collection + foreach (string s in dico.Keys) + { + WriteLine(s); + } + WriteLine("***********************"); + + //Values permet d'obtenir toutes les valeurs en une collection + foreach (int i in dico.Values) + { + WriteLine(i); + } + + + + // il existe plusieurs dictionnaires en C# : + // - ListDictionary : non générique, utilise en interne une liste simplement chaînée. + // son seul intérêt est pour l'utilisation de dictionnaires avec une dizaine de paires clé-valeur uniquement. + // - OrderedDictionary : non générique, NON trié. Il conserve l'ordre d'insertion et permet d'accéder aux éléments par indice. + // - SortedDictionary : générique, utilise un red/black tree. Trie les paires en comparant les clés lors de l'insertion. + // - SortedList : générique, utilise un double tableau. Trie les paires clé-valeur en comparant les clés lors de l'insertion et permet d'accéder aux éléments par indice + WriteLine("Insertion de [\"mille\", 1000], [\"dix\", 10] et [\"cent\", 100] dans un Dictionary"); + Dictionary d = new Dictionary(); + d.Add("mille", 1000); + d.Add("dix", 10); + d.Add("cent", 100); + foreach (KeyValuePair pair in d) + { + WriteLine($"{pair.Key} - {pair.Value}"); + } + WriteLine("***********************\n"); + + WriteLine("Insertion de [1000, \"mille\"], [10, \"dix\"] et [100, \"cent\"] dans un SortedDictionary"); + SortedDictionary sd = new SortedDictionary(); + sd.Add(1000, "mille"); + sd.Add(10, "dix"); + sd.Add(100, "cent"); + foreach (KeyValuePair pair in sd) + { + WriteLine($"{pair.Key} - {pair.Value}"); + } + WriteLine("***********************\n"); + + WriteLine("Insertion de [1000, \"mille\"], [10, \"dix\"] et [100, \"cent\"] dans un SortedList"); + SortedList sl = new SortedList(); + sl.Add(1000, "mille"); + sl.Add(10, "dix"); + sl.Add(100, "cent"); + foreach (KeyValuePair pair in sl) + { + WriteLine($"{pair.Key} - {pair.Value}"); + } + WriteLine("***********************\n"); + + WriteLine("Insertion de [1000, \"mille\"], [10, \"dix\"] et [100, \"cent\"] dans un OrderedDictionary"); + OrderedDictionary od = new OrderedDictionary(); + od.Add(1000, "mille"); + od.Add(10, "dix"); + od.Add(100, "cent"); + foreach (DictionaryEntry pair in od) + { + WriteLine($"{pair.Key} - {pair.Value}"); + } + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_014_Dictionary/ex_023_014_Dictionary.csproj b/p04_AdvancedCSharp/ex_023_014_Dictionary/ex_023_014_Dictionary.csproj new file mode 100644 index 0000000..dadf3f9 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_014_Dictionary/ex_023_014_Dictionary.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_014_Dictionary + Exe + ex_023_014_Dictionary + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/Nounours.cs b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/Nounours.cs new file mode 100644 index 0000000..cf653b8 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/Nounours.cs @@ -0,0 +1,92 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; + +namespace ex_023_015_DictionaryCustomType +{ + class Nounours : IEquatable + { + public string Name + { + get; + private set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public Nounours(string name, DateTime dateDeNaissance, int nbPoils) + { + Name = name; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + } + + //... + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return (DateDeNaissance.Year * 1000 + DateDeNaissance.DayOfYear) * Name.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Name.Equals(other.Name) && this.DateDeNaissance.Equals(other.DateDeNaissance)); + } + + + } +} diff --git a/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/NounoursNbPoilsEqualityComparer.cs b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/NounoursNbPoilsEqualityComparer.cs new file mode 100644 index 0000000..bcf0a94 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/NounoursNbPoilsEqualityComparer.cs @@ -0,0 +1,28 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursNbPoilsEqualityComparer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_023_015_DictionaryCustomType +{ + class NounoursNbPoilsEqualityComparer : EqualityComparer + { + public override bool Equals(Nounours x, Nounours y) + { + return x.NbPoils == y.NbPoils; + } + + public override int GetHashCode(Nounours obj) + { + return obj.NbPoils; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/Program.cs b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/Program.cs new file mode 100644 index 0000000..ceed9cd --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/Program.cs @@ -0,0 +1,150 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using static System.Console; + +namespace ex_023_015_DictionaryCustomType +{ + class Program + { + /// + /// exemple d'utilisation d'un dictionnaire sur un type personnalisé (une classe Nounours) + /// 1. dans le premier cas, la classe (VieuxNounours) n'implémente pas le protocole d'égalité. + /// L'exemple montre les problèmes qui peuvent apparaître : deux instances a priori égales ne sont pas comprises par le dictionnaire comme étant la même + /// 2. dans le deuxième cas, la classe (Nounours) implémente le protocole d'égalité. + /// Plus de problème. + /// + /// + static void Main(string[] args) + { + WriteLine("*****************************"); + WriteLine("TEST SANS PROTOCOLE D'EGALITE"); + WriteLine("*****************************"); + TestAvecVieuxNounours(); + + WriteLine("\n\n\n"); + WriteLine("*****************************"); + WriteLine("TEST AVEC PROTOCOLE D'EGALITE"); + WriteLine("*****************************"); + TestAvecNounours(); + } + + static void TestAvecVieuxNounours() + { + VieuxNounours mouton = new VieuxNounours("mouton", new DateTime(2005, 04, 03), 2000); + VieuxNounours ours = new VieuxNounours("ours", new DateTime(2006, 05, 04), 3000); + VieuxNounours chien = new VieuxNounours("chien", new DateTime(2007, 06, 05), 1500); + VieuxNounours girafe = new VieuxNounours("girafe", new DateTime(2008, 07, 06), 500); + VieuxNounours dromadaire = new VieuxNounours("dromadaire", new DateTime(2012, 3, 11), 500); + + //préparation du dictionnaire + var dico = new Dictionary() + { + [mouton] = 0, + [ours] = 0, + [chien] = 0, + [girafe] = 0, + [dromadaire] = 0, + }; + //on peut aussi utiliser cet equality comparer pour éviter le problème suivant + //var dico = new Dictionary(new VieuxNounoursNbPoilsEqualityComparer()); + + //affichage du dictionnaire + DisplayVieuxDico(dico); + + //on incrémente la valeur associée à la clé mouton, et celle associée à la clé chien + dico[mouton]++; + dico[chien]++; + DisplayVieuxDico(dico); + + //on crée un nouveau chien (qui a les mêmes données que le premier, mais la référence n'est pas la même) + VieuxNounours chien2 = new VieuxNounours("chien", new DateTime(2007, 06, 05), 1500); + + //chien2 n'est pas trouvé dans le dictionnaire car chien2 != chien, car ce sont des références différentes + //(le protocole d'égalité n'a pas été réécrit) + WriteLine(dico.ContainsKey(chien2)); + if (dico.ContainsKey(chien2)) + { + dico[chien2]++; + } + else + { + dico.Add(chien2, 1); + } + DisplayVieuxDico(dico); + } + + static void DisplayVieuxDico(Dictionary dico) + { + WriteLine("**********************"); + foreach (KeyValuePair pair in dico) + { + WriteLine($"{pair.Key.Name} {pair.Value}"); + } + WriteLine("**********************"); + } + + static void TestAvecNounours() + { + Nounours mouton = new Nounours("mouton", new DateTime(2005, 04, 03), 2000); + Nounours ours = new Nounours("ours", new DateTime(2006, 05, 04), 3000); + Nounours chien = new Nounours("chien", new DateTime(2007, 06, 05), 1500); + Nounours girafe = new Nounours("girafe", new DateTime(2008, 07, 06), 500); + Nounours dromadaire = new Nounours("dromadaire", new DateTime(2012, 3, 11), 500); + + //préparation du dictionnaire + var dico = new Dictionary() + { + [mouton] = 0, + [ours] = 0, + [chien] = 0, + [girafe] = 0, + [dromadaire] = 0, + }; + //var dico = new Dictionary(new NounoursNbPoilsEqualityComparer()); + + //affichage du dictionnaire + DisplayDico(dico); + + //on incrémente la valeur associée à la clé mouton, et celle associée à la clé chien dico[mouton]++; + dico[chien]++; + DisplayDico(dico); + + //on crée un nouveau chien (qui a les mêmes données que le premier, mais la référence n'est pas la même) + Nounours chien2 = new Nounours("chien", new DateTime(2007, 06, 05), 1500); + + //chien2 est trouvé dans le dictionnaire car chien2 == chien, d'après le protocole d'égalité + //(même si les références sont différentes) + WriteLine(dico.ContainsKey(chien2)); + if (dico.ContainsKey(chien2)) + { + dico[chien2]++; + } + else + { + dico.Add(chien2, 1); + } + DisplayDico(dico); + } + + static void DisplayDico(Dictionary dico) + { + WriteLine("**********************"); + foreach (KeyValuePair pair in dico) + { + WriteLine($"{pair.Key.Name} {pair.Value}"); + } + WriteLine("**********************"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/VieuxNounours.cs b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/VieuxNounours.cs new file mode 100644 index 0000000..cd09cd2 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/VieuxNounours.cs @@ -0,0 +1,43 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : VieuxNounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-29 +// +// ======================================================================== + +using System; + +namespace ex_023_015_DictionaryCustomType +{ + class VieuxNounours + { + public string Name + { + get; + private set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public VieuxNounours(string name, DateTime dateDeNaissance, int nbPoils) + { + Name = name; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/ex_023_015_DictionaryCustomType.csproj b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/ex_023_015_DictionaryCustomType.csproj new file mode 100644 index 0000000..4db5387 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_015_DictionaryCustomType/ex_023_015_DictionaryCustomType.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_015_DictionaryCustomType + Exe + ex_023_015_DictionaryCustomType + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/MonLit.cs b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/MonLit.cs new file mode 100644 index 0000000..a63c5a5 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/MonLit.cs @@ -0,0 +1,130 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MonLit.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_023_016_ReadOnlyCollection +{ + /// + /// L'exemple suivant montre comment encapsuler une collection d'un type dans les deux cas principaux suivants : + /// 1) le type est immuable (en façade au moins), c'est-à-dire qu'on ne peut pas modifier son état interne en appelant ses méthodes ou propriétés + /// 2) le type est mutable, ie que l'utilisateur peut modifier l'état interne de ses instances, et notre API l'autorise. + /// Comment encapsuler correctement une collection d'un tel type ? + /// Dans l'exemple suivant, le type Nounours est immuable, nous voulons protéger la collection contre : + /// - les modifications de la collection (ajout ou suppression d'éléments), + /// - la modification de la collection elle-même (on ne doit pas pouvoir faire de new) + /// Nous ne cherchons pas à protéger les éléments de la collection (en particulier si le type n'est pas immuable). + /// En résumé, nous cherchons à rendre publique en lecture seule, la collection mNounours privée de MonLit. + /// + class MonLit + { + //on veut encapsuler cette collection d'un type immuable + private List mNounours = new List(new Nounours[] { + new Nounours(1, "Beluga", new DateTime(2012, 07, 29), 0), + new Nounours(2, "Singe", new DateTime(2009, 08, 09), 1345), + new Nounours(3, "Girafe", new DateTime(2007, 11, 02), 567)}); + + /// + /// Tentative 1 (mauvaise) : + /// Ceci est absolument très très mauvais. La propriété semble en lecture seule car le setter est privé, mais la List est type référence. + /// Certes, on ne peut pas faire NounoursList = new List(); car le setter est privé, + /// mais on peut faire par exemple NounoursList[i] = new Nounours(...); + /// ou bien, NounoursList.Clear();, NounoursList.RemoveAt(i); NounoursList.Add(...); + /// ... + /// Cette solution ne protège que du new. + /// + public List NounoursList + { + get + { + return mNounours; + } + private set + { + mNounours = value; + } + } + + /// + /// Tentative 2 (moins mauvaise, mais mauvaise quand même) : + /// On a l'impression, en utilisant le type de plus haut niveau, ici IEnumerable, d'empêcher toute action. + /// Malheureusement, un utilisateur de notre classe, mais s'il n'est pas mal intentionné, peut tenter : + /// var temp = (NounoursIEnumerable as List); + /// temp.Add(...); + /// temp.Clear(); + /// ... + /// Il peut donc faire les mêmes dégâts que précédemment, même si le fait d'avoir un IEnumerable devrait l'inciter à ne pas le faire. + /// + public IEnumerable NounoursIEnumerable + { + get + { + return mNounours; + } + } + + /// + /// Tentative 3 (quasi-identique à la précédente) : + /// On a l'impression, en utilisant le type de plus haut niveau, ici IReadOnlyCollection, d'empêcher toute action. + /// Malheureusement, un utilisateur de notre classe, mais s'il n'est pas mal intentionné, peut tenter : + /// var temp = (NounoursIROC as List); + /// temp.Add(...); + /// temp.Clear(); + /// ... + /// Il peut donc faire les mêmes dégâts que précédemment, même si le fait d'avoir un IEnumerable devrait l'inciter à ne pas le faire. + /// + public IReadOnlyCollection NounoursIROC + { + get + { + return mNounours; + } + } + + //parfait pour encapsuler un type immuable + /// + /// Solution (la bonne !) + /// Ici, on déclare une collection ReadOnlyCollection : il s'agit d'un wrapper autour de la collection mNounours. + /// Ce wrapper est initialisé dans le constructeur de MonLit. + /// Le setter privé de NounoursROC empêche de réinitialiser le wrapper (pas d'appel du new). + /// ReadOnlyCollection empêche l'appel des méthodes Add, Remove, Clear... + /// On ne peut pas caster NounoursROC en List car il ne s'agit pas de la même instance + /// (NounoursROC n'est pas la même référence que mNounours, un de ses membres la référence privée mNounours). + /// + /// Avantage énorme : tous les changements de mNounours sont directement répercutés sur NounoursROC puisqu'il l'enveloppe. + /// + /// Attention : si la référence mNounours change (appel de new ou de =), alors NounoursROC n'enveloppe plus mNounours, mais l'ancienne collection mNounours. + /// + public System.Collections.ObjectModel.ReadOnlyCollection NounoursROC + { + get; + private set; + } + + public MonLit() + { + NounoursROC = new System.Collections.ObjectModel.ReadOnlyCollection(mNounours); + } + + /// + /// Variante de la solution + /// Cette solution donne les mêmes résultats que la précédente à quelques différences près : + /// - avantage : pas besoin d'initialiser dans le constructeur ou de réinitialiser si la référence mNounours change (appel de new ou =) + /// => celle-ci semble donc mieux que la précédente + /// - inconvénient : à chaque fois qu'on appelle NounoursROC2, on recrée un nouveau wrapper. + /// => la solution précédente semble donc moins coûteuse en appel de méthodes, même s'il est vrai que AsReadOnly ne coûte pas très cher. + /// Conclusion : choisissez l'une des deux solutions, comme vous voulez ! + /// + public System.Collections.ObjectModel.ReadOnlyCollection NounoursROC2 => mNounours.AsReadOnly(); + + } +} diff --git a/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/MonLit2.cs b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/MonLit2.cs new file mode 100644 index 0000000..66b8467 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/MonLit2.cs @@ -0,0 +1,131 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MonLit2.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_023_016_ReadOnlyCollection +{ + /// + /// L'exemple suivant montre comment encapsuler une collection d'un type dans les deux cas principaux suivants : + /// 1) le type est immuable (en façade au moins), c'est-à-dire qu'on ne peut pas modifier son état interne en appelant ses méthodes ou propriétés + /// 2) le type est mutable, ie que l'utilisateur peut modifier l'état interne de ses instances, et notre API l'autorise. + /// Comment encapsuler correctement une collection d'un tel type ? + /// Dans l'exemple suivant, le type Nounours2 est mutable, nous voulons protéger la collection contre : + /// - les modifications de la collection (ajout ou suppression d'éléments), + /// - la modification de la collection elle-même (on ne doit pas pouvoir faire de new) + /// Nous ne cherchons pas à protéger les éléments de la collection (en particulier si le type n'est pas immuable). + /// En résumé, nous cherchons à rendre publique en lecture seule, la collection mNounours2 privée de MonLit2. + /// + class MonLit2 + { + //on veut encapsuler cette collection d'un type immuable + private List mNounours2 = new List(new Nounours2[] { + new Nounours2(1, "Beluga", new DateTime(2012, 07, 29), 0), + new Nounours2(2, "Singe", new DateTime(2009, 08, 09), 1345), + new Nounours2(2, "Truite", new DateTime(2013, 04, 3), 0), + new Nounours2(3, "Girafe", new DateTime(2007, 11, 02), 567)}); + + /// + /// Tentative 1 (mauvaise) : + /// Ceci est absolument très très mauvais. La propriété semble en lecture seule car le setter est privé, mais la List est type référence. + /// Certes, on ne peut pas faire Nounours2List = new List(); car le setter est privé, + /// mais on peut faire par exemple Nounours2List[i] = new Nounours2(...); + /// ou bien, Nounours2List.Clear();, Nounours2List.RemoveAt(i); Nounours2List.Add(...); + /// ... + /// Cette solution ne protège que du new. + /// + public List Nounours2List + { + get + { + return mNounours2; + } + private set + { + mNounours2 = value; + } + } + + /// + /// Tentative 2 (moins mauvaise, mais mauvaise quand même) : + /// On a l'impression, en utilisant le type de plus haut niveau, ici IEnumerable, d'empêcher toute action. + /// Malheureusement, un utilisateur de notre classe, mais s'il n'est pas mal intentionné, peut tenter : + /// var temp = (Nounours2IEnumerable as List); + /// temp.Add(...); + /// temp.Clear(); + /// ... + /// Il peut donc faire les mêmes dégâts que précédemment, même si le fait d'avoir un IEnumerable devrait l'inciter à ne pas le faire. + /// + public IEnumerable Nounours2IEnumerable + { + get + { + return mNounours2; + } + } + + /// + /// Tentative 3 (quasi-identique à la précédente) : + /// On a l'impression, en utilisant le type de plus haut niveau, ici IReadOnlyCollection, d'empêcher toute action. + /// Malheureusement, un utilisateur de notre classe, mais s'il n'est pas mal intentionné, peut tenter : + /// var temp = (Nounours2IROC as List); + /// temp.Add(...); + /// temp.Clear(); + /// ... + /// Il peut donc faire les mêmes dégâts que précédemment, même si le fait d'avoir un IEnumerable devrait l'inciter à ne pas le faire. + /// + public IReadOnlyCollection Nounours2IROC + { + get + { + return mNounours2; + } + } + + //parfait pour encapsuler un type immuable + /// + /// Solution (la bonne !) + /// Ici, on déclare une collection ReadOnlyCollection : il s'agit d'un wrapper autour de la collection mNounours2. + /// Ce wrapper est initialisé dans le constructeur de MonLit. + /// Le setter privé de Nounours2ROC empêche de réinitialiser le wrapper (pas d'appel du new). + /// ReadOnlyCollection empêche l'appel des méthodes Add, Remove, Clear... + /// On ne peut pas caster Nounours2ROC en List car il ne s'agit pas de la même instance + /// (Nounours2ROC n'est pas la même référence que mNounours2, un de ses membres la référence privée mNounours2). + /// + /// Avantage énorme : tous les changements de mNounours2 sont directement répercutés sur Nounours2ROC puisqu'il l'enveloppe. + /// + /// Attention : si la référence mNounours2 change (appel de new ou de =), alors Nounours2ROC n'enveloppe plus mNounours2, mais l'ancienne collection mNounours2. + /// + public System.Collections.ObjectModel.ReadOnlyCollection Nounours2ROC + { + get; + private set; + } + + public MonLit2() + { + Nounours2ROC = new System.Collections.ObjectModel.ReadOnlyCollection(mNounours2); + } + + /// + /// Variante de la solution + /// Cette solution donne les mêmes résultats que la précédente à quelques différences près : + /// - avantage : pas besoin d'initialiser dans le constructeur ou de réinitialiser si la référence mNounours2 change (appel de new ou =) + /// => celle-ci semble donc mieux que la précédente + /// - inconvénient : à chaque fois qu'on appelle Nounours2ROC2, on recrée un nouveau wrapper. + /// => la solution précédente semble donc moins coûteuse en appel de méthodes, même s'il est vrai que AsReadOnly ne coûte pas très cher. + /// Conclusion : choisissez l'une des deux solutions, comme vous voulez ! + /// + public System.Collections.ObjectModel.ReadOnlyCollection Nounours2ROC2 => mNounours2.AsReadOnly(); + + } +} diff --git a/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Nounours.cs b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Nounours.cs new file mode 100644 index 0000000..750af02 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Nounours.cs @@ -0,0 +1,53 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using System; + +namespace ex_023_016_ReadOnlyCollection +{ + /// + /// Nounours est immuable + /// + struct Nounours + { + public int Id + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public Nounours(int id, string name, DateTime dateDeNaissance, int nbPoils) + { + Id = id; + Name = name; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Nounours2.cs b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Nounours2.cs new file mode 100644 index 0000000..4ea16bd --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Nounours2.cs @@ -0,0 +1,53 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours2.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using System; + +namespace ex_023_016_ReadOnlyCollection +{ + /// + /// Nounours est mutable (Name et NbPoils ont un setter public) + /// + class Nounours2 + { + public int Id + { + get; + private set; + } + + public string Nom + { + get; + set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + set; + } + + public Nounours2(int id, string nom, DateTime dateDeNaissance, int nbPoils) + { + Id = id; + Nom = nom; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Program.cs b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Program.cs new file mode 100644 index 0000000..e5d690f --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/Program.cs @@ -0,0 +1,72 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_023_016_ReadOnlyCollection +{ + class Program + { + /// + /// L'exemple suivant montre comment encapsuler une collection d'un type dans les deux cas principaux suivants : + /// 1) le type est immuable (en façade au moins), c'est-à-dire qu'on ne peut pas modifier son état interne en appelant ses méthodes ou propriétés + /// => MonLit possède une collection privée mNounours de Nounours où Nounours est immuable + /// 2) le type est mutable, ie que l'utilisateur peut modifier l'état interne de ses instances, et notre API l'autorise. + /// => MonLit2 possède une collection privée mNounours2 de Nounours2 où Nounours2 est mutable + /// Comment encapsuler correctement une collection d'un tel type ? + /// Dans l'exemple suivant, nous voulons protéger la collection contre : + /// - les modifications de la collection (ajout ou suppression d'éléments), + /// - la modification de la collection elle-même (on ne doit pas pouvoir faire de new) + /// Nous ne cherchons pas à protéger les éléments de la collection (en particulier si le type n'est pas immuable). + /// En résumé, nous cherchons à rendre publique en lecture seule, la collection privée de nounours du lit. + /// + static void Main(string[] args) + { + //Test avec MonLit qui possède une collection d'un type immuable (Nounours) + MonLit monlit = new MonLit(); + + monlit.NounoursList.RemoveAt(0); // dangereux ! + + (monlit.NounoursIEnumerable as List).RemoveAt(0); // c'est mieux, mais pas suffisant... + + (monlit.NounoursIROC as List).RemoveAt(0); // idem + + //List test = (monlit.NounoursROC as List); // pas possible + //monlit.NounoursROC[0] = new Nounours(5, "betterave", DateTime.Now, 0); // pas possible + + //List test = (monlit.NounoursROC2 as List); // pas possible + //monlit.NounoursROC2[0] = new Nounours(5, "betterave", DateTime.Now, 0); // pas possible + + + + + + //Test avec MonLit2 qui possède une collection d'un type mutable (Nounours2) + MonLit2 monlit2 = new MonLit2(); + + monlit2.Nounours2List.RemoveAt(0); // dangereux ! + + (monlit2.Nounours2IEnumerable as List).RemoveAt(0); // c'est mieux, mais pas suffisant... + + (monlit2.Nounours2IROC as List).RemoveAt(0); // idem + + //List test = (monlit2.Nounours2ROC as List); // pas possible + //monlit2.Nounours2ROC[0] = new Nounours2(5, "betterave", DateTime.Now, 0); // pas possible + + //List test = (monlit2.Nounours2ROC2 as List); // pas possible + //monlit2.Nounours2ROC2[0] = new Nounours2(5, "betterave", DateTime.Now, 0); // pas possible + + //on peut toujours modifier les instances de Nounours2, mais c'était voulu ! + monlit2.Nounours2ROC[0].NbPoils = 1; + + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/ex_023_016_ReadOnlyCollection.csproj b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/ex_023_016_ReadOnlyCollection.csproj new file mode 100644 index 0000000..36647bf --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_016_ReadOnlyCollection/ex_023_016_ReadOnlyCollection.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_016_ReadOnlyCollection + Exe + ex_023_016_ReadOnlyCollection + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/INounours.cs b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/INounours.cs new file mode 100644 index 0000000..19b921a --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/INounours.cs @@ -0,0 +1,43 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : INounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using System; + +namespace ex_023_017_Deep_Read_only_collections_dll +{ + /// + /// INounours est une façade immuable de Nounours : + /// Nounours est un type mutable interne, mais INounours n'offre accès publiquement qu'à des méthodes de lecture. + /// En accédant à la référence via le type INounours, elle aparaît immuable, en façade. + /// + public interface INounours + { + int Id + { + get; + } + + string Name + { + get; + } + + DateTime DateDeNaissance + { + get; + } + + int NbPoils + { + get; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/MonLit.cs b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/MonLit.cs new file mode 100644 index 0000000..24d047d --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/MonLit.cs @@ -0,0 +1,91 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MonLit.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_023_017_Deep_Read_only_collections_dll +{ + /// + /// L'exemple suivant montre comment encapsuler une collection d'un type dans le cas suivant : + /// => le type est mutable, c'est-à-dire qu'on peut modifier son état interne en appelant ses méthodes ou propriétés + /// => MonLit possède une collection privée mNounours de Nounours où Nounours est mutable + /// Comment encapsuler correctement une collection d'un tel type ? + /// Dans l'exemple suivant, nous voulons protéger la collection contre : + /// - les modifications de la collection (ajout ou suppression d'éléments), + /// - la modification de la collection elle-même (on ne doit pas pouvoir faire de new) + /// - la modification de chaque élément de la collection : on ne doit pas pouvoir faire de new, ni appeler des méthodes ou propriétés mutables. + /// + /// En résumé, nous cherchons à rendre publique en lecture seule, la collection privée de nounours du lit, ainsi que chaque élément. + /// + /// L'exemple 023_015 montrait comment encapsuler une collection d'un type immuable ou d'un type volontairement laissé mutable. + /// Tous les mauvais cas présentés dans l'exemple 023_015 sont toujours mauvais ici, et ne sont donc pas représentés. + /// Le solution qui avait été retenu dans l'exemple 023_015 consistait à utiliser un wrapper ReadOnlyCollection. + /// Cette solution n'est pas envisageable si le type est mutable et que nous cherchons à le protéger. + /// + /// La bonne solution consiste à : + /// - rendre le type interne (Nounours) + /// c'est la raison pour laquelle cet exemple est sur deux assemblages : + /// . une bibliothèque de classes contenant le type interne et une classe contenant une collection privée de ce type ; + /// . un exécutable consommant la classe contenant la collection à encapsuler. + /// - faire une façade immuable publique de ce type (INounours) + /// cette façade immuable ne contient que des propriétés et méthodes en lecture seule + /// - profiter de la covariance des interfaces (IEnumerable, IReadOnlyCollection et IReadOnlyList) + /// et encapsuler la collection privée du type mutable interne avec une collection en lecture seule de la façade immuable + /// => en effet : + /// + les types IEnumerable, IReadOnlyCollection et IReadOnlyList sont des collections en lecture seule, elles ne sont donc pas modifiables + /// + elles ne peuvent pas être castées en une collection modifiable du type mutable à l'extérieur de la bibliothèque de classes car celui-ci est interne à la bibliothèque + /// + elles ne peuvent pas être castées en une collection modificable de la façade immuable car les classes (comme List, Array, Queue...) ne sont pas covariantes. + /// => C'EST GAGNE !!! + public class MonLit + { + //on veut encapsuler une collection d'un type muable + private List mNounours = new List(new Nounours[] { + new Nounours(1, "Beluga", new DateTime(2012, 07, 29), 0), + new Nounours(2, "Singe", new DateTime(2009, 08, 09), 1345), + new Nounours(3, "Girafe", new DateTime(2007, 11, 02), 567)}); + + //Les solutions suivantes sont toutes OK si Nounours reste internal à la bibliothèque et INounours public en façade immuable + + /// + /// Avec un IEnumerable, aucun membre n'est exposé, on ne peut que parcourir la collection (type de plus haut niveau) + /// + public IEnumerable MesNounoursIEnumerable + { + get + { + return mNounours; + } + } + + /// + /// IReadOnlyCollection expose la propriété Count en plus de ce qu'autorise IEnumerable + /// + public IReadOnlyCollection MesNounoursIReadOnlyCollection + { + get + { + return mNounours; + } + } + + /// + /// IReadOnlyList expose un indexeur en plus de ce qu'autorise IReadOnlyCollection + /// + public IReadOnlyList MesNounoursIReadOnlyList + { + get + { + return mNounours; + } + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/Nounours.cs b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/Nounours.cs new file mode 100644 index 0000000..f138762 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/Nounours.cs @@ -0,0 +1,54 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using System; + +namespace ex_023_017_Deep_Read_only_collections_dll +{ + /// + /// Nounours est un type mutable, interne (pas de modificateur de visibilité devant class Nounours, donc par défaut, c'est internal) + /// Le type Nounours n'est donc accessible qu'à l'intérieur de l'assemblage dans lequel il est défini. + /// + class Nounours : INounours + { + public int Id + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + set; + } + + public Nounours(int id, string name, DateTime dateDeNaissance, int nbPoils) + { + Id = id; + Name = name; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/ex_023_017_Deep_Read_only_collections_dll.csproj b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/ex_023_017_Deep_Read_only_collections_dll.csproj new file mode 100644 index 0000000..f2a630d --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_dll/ex_023_017_Deep_Read_only_collections_dll.csproj @@ -0,0 +1,11 @@ + + + netstandard2.0 + ex_023_017_Deep_Read_only_collections_dll + ex_023_017_Deep_Read_only_collections_dll + 1.6.0 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_exe/Program.cs b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_exe/Program.cs new file mode 100644 index 0000000..1594e47 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_exe/Program.cs @@ -0,0 +1,121 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-09-30 +// +// ======================================================================== + +using static System.Console; +using System.Collections.Generic; +using ex_023_017_Deep_Read_only_collections_dll; +using System.Text; + +namespace ex_023_017_Deep_Read_only_collections_exe +{ + class Program + { + /// + /// L'exemple suivant montre comment encapsuler une collection d'un type dans le cas suivant : + /// => le type est mutable, c'est-à-dire qu'on peut modifier son état interne en appelant ses méthodes ou propriétés + /// => MonLit possède une collection privée mNounours de Nounours où Nounours est mutable + /// Comment encapsuler correctement une collection d'un tel type ? + /// Dans l'exemple suivant, nous voulons protéger la collection contre : + /// - les modifications de la collection (ajout ou suppression d'éléments), + /// - la modification de la collection elle-même (on ne doit pas pouvoir faire de new) + /// - la modification de chaque élément de la collection : on ne doit pas pouvoir faire de new, ni appeler des méthodes ou propriétés mutables. + /// + /// En résumé, nous cherchons à rendre publique en lecture seule, la collection privée de nounours du lit, ainsi que chaque élément. + /// + /// L'exemple 023_015 montrait comment encapsuler une collection d'un type immuable ou d'un type volontairement laissé mutable. + /// Tous les mauvais cas présentés dans l'exemple 023_015 sont toujours mauvais ici, et ne sont donc pas représentés. + /// Le solution qui avait été retenu dans l'exemple 023_015 consistait à utiliser un wrapper ReadOnlyCollection. + /// Cette solution n'est pas envisageable si le type est mutable et que nous cherchons à le protéger. + /// + /// La bonne solution consiste à : + /// - rendre le type interne (Nounours) + /// c'est la raison pour laquelle cet exemple est sur deux assemblages : + /// . une bibliothèque de classes contenant le type interne et une classe contenant une collection privée de ce type ; + /// . un exécutable consommant la classe contenant la collection à encapsuler. + /// - faire une façade immuable publique de ce type (INounours) + /// cette façade immuable ne contient que des propriétés et méthodes en lecture seule + /// - profiter de la covariance des interfaces (IEnumerable, IReadOnlyCollection et IReadOnlyList) + /// et encapsuler la collection privée du type mutable interne avec une collection en lecture seule de la façade immuable + /// => en effet : + /// + les types IEnumerable, IReadOnlyCollection et IReadOnlyList sont des collections en lecture seule, elles ne sont donc pas modifiables + /// + elles ne peuvent pas être castées en une collection modifiable du type mutable à l'extérieur de la bibliothèque de classes car celui-ci est interne à la bibliothèque + /// + elles ne peuvent pas être castées en une collection modificable de la façade immuable car les classes (comme List, Array, Queue...) ne sont pas covariantes. + /// => C'EST GAGNE !!! + /// + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + MonLit monlit = new MonLit(); + + //ce qu'on voulait empêcher est empêché : on ne peut pas appeler les setters publiques car on utilise des éléments du type de la façade immuable INounours + //il ne sont donc accessibles qu'en lecture seule + // monlit.MesNounoursIEnumerable.ElementAt(0).NbPoils -= 100; + + + //Essayons maintenant de tout casser : + + //Tentative 1 : caster MesNounours en List + //impossible car le type Nounours est interne à la bibliothèque et n'est donc pas accessible dans un autre assemblage + // List test = monlit.MesNounoursIEnumerable as List; + // List test2 = monlit.MesNounoursIReadOnlyCollection as List; + // List test3 = monlit.MesNounoursIReadOnlyList as List; + + //Tentative 2 : caster MesNounours en List pour pouvoir modifier la collection + //impossible car les classes, comme List, ne sont pas covariantes, alors que les interfaces le sont + // on ne peut donc pas caster List en List avec Nounours implémentant INounours + // une exception est lancée + List test4 = monlit.MesNounoursIEnumerable as List; + string result4 = test4 == null ? "échec du cast de IEnumerable vers List" : "cast de IEnumerable vers List réussi"; + WriteLine(result4); + + List test5 = monlit.MesNounoursIReadOnlyCollection as List; + string result5 = test4 == null ? "échec du cast de IReadOnlyCollection vers List" : "cast de IReadOnlyCollection vers List réussi"; + WriteLine(result5); + + List test6 = monlit.MesNounoursIReadOnlyList as List; + string result6 = test4 == null ? "échec du cast de IReadOnlyList vers List" : "cast de IReadOnlyList vers List réussi"; + WriteLine(result6); + + //Tentative 3 : caster un élément de la collection en Nounours pour pouvoir le modifier + //impossible puisque Nounours est interne et n'est donc pas accessible dans un autre assemblage que celui dans lequel il a été défini + //(monlit.MesNounoursIEnumerable.ElementAt(0) as Nounours).NbPoils += 100; + //(monlit.MesNounoursIReadOnlyCollection.ElementAt(0) as Nounours).NbPoils += 100; + //(monlit.MesNounoursIReadOnlyList.ElementAt(0) as Nounours).NbPoils += 100; + + WriteLine(); + + //ET VOILA CE QU'ON PEUT FAIRE : + WriteLine("Avec IEnumerable :"); + foreach (var n in monlit.MesNounoursIEnumerable) + { + WriteLine($"\t{n}"); + } + + WriteLine(); + WriteLine("Avec IReadOnlyCollection :"); + int nbNounours = monlit.MesNounoursIReadOnlyCollection.Count; + foreach (var n in monlit.MesNounoursIReadOnlyCollection) + { + WriteLine($"\t{n}"); + } + + WriteLine(); + WriteLine("Avec IReadOnlyList :"); + nbNounours = monlit.MesNounoursIReadOnlyList.Count; + for (int i = 0; i < nbNounours; i++) + { + WriteLine($"\t{i+1}/{nbNounours} : {monlit.MesNounoursIReadOnlyList[i]}"); + } + + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_exe/ex_023_017_Deep_Read_only_collections_exe.csproj b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_exe/ex_023_017_Deep_Read_only_collections_exe.csproj new file mode 100644 index 0000000..655f479 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_017_Deep_Read_only_collections_exe/ex_023_017_Deep_Read_only_collections_exe.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_023_017_Deep_Read_only_collections_exe + Exe + ex_023_017_Deep_Read_only_collections_exe + 6.0.6 + false + false + false + + + + + diff --git a/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/MonLit.cs b/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/MonLit.cs new file mode 100644 index 0000000..980a823 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/MonLit.cs @@ -0,0 +1,54 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MonLit.cs +// Author : Marc Chevaldonné +// Creation date : 2016-01-10 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace ex_023_018_ReadOnlyDictionaries +{ + /// + /// L'exemple suivant montre comment encapsuler un dictionnaire dans les cas suivants : + /// => les clés et/ou valeurs sont mutables, c'est-à-dire qu'on peut modifier leur état interne en appelant leurs méthodes ou propriétés + /// => MonLit possède un dictionnaire de paire clé (string)- valeur (Nounours) privée mNounoursDico où Nounours est mutable + /// Comment encapsuler correctement un dictionnaire de ce type ? + /// Dans l'exemple suivant, nous voulons protéger le dictionnaire contre : + /// - les modifications du dictionnaire (ajout ou suppression d'éléments), + /// - la modification du dictionnaire lui-même (on ne doit pas pouvoir faire de new) + /// + /// En résumé, nous cherchons à rendre publique en lecture seule, le dictionnaire privé, en laissant chacun de ses éléments modifiables. + /// + /// La bonne solution consiste à : + /// - envelopper (wrapper) le dictionnaire privé avec un ReadOnlyDictionary construit dans le constructeur de MonLit. + /// - tant qu'en interne, dans la classe MonLit, on ne change pas la référence de mNounoursDico, le wrapper donne accès en lecture seule au dictionnaire + /// - attention de bien penser à le reconstruire si la référence change !!! + public class MonLit + { + //on veut encapsuler une collection d'un type muable + private Dictionary mNounoursDico = new Dictionary + { + ["Beluga"] = new Nounours(0, "Beluga", new DateTime(2012, 07, 29), 0), + ["Singe"] = new Nounours(1, "Singe", new DateTime(2009, 08, 09), 1345), + ["Girafe"] = new Nounours(2, "Girafe", new DateTime(2007, 11, 02), 567) + }; + + public ReadOnlyDictionary Nounours + { + get; + private set; + } + + public MonLit() + { + Nounours = new ReadOnlyDictionary(mNounoursDico); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/Nounours.cs b/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/Nounours.cs new file mode 100644 index 0000000..a3a9911 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/Nounours.cs @@ -0,0 +1,99 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// +// ======================================================================== + +using System; + +namespace ex_023_018_ReadOnlyDictionaries +{ + public class Nounours : IEquatable + { + public int Id + { + get; + private set; + } + + public string Nom + { + get; + set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + set; + } + + public Nounours(int id, string nom, DateTime dateDeNaissance, int nbPoils) + { + Id = id; + Nom = nom; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + } + + //... + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return (DateDeNaissance.Year * 1000 + DateDeNaissance.DayOfYear) * Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance.Equals(other.DateDeNaissance)); + } + + + } +} diff --git a/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/Program.cs b/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/Program.cs new file mode 100644 index 0000000..3a0eaeb --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/Program.cs @@ -0,0 +1,49 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-01-10 +// +// ======================================================================== + +using static System.Console; + +namespace ex_023_018_ReadOnlyDictionaries +{ + class Program + { + /// + /// L'exemple suivant montre comment encapsuler un dictionnaire dans les cas suivants : + /// => les clés et/ou valeurs sont mutables, c'est-à-dire qu'on peut modifier leur état interne en appelant leurs méthodes ou propriétés + /// => MonLit possède un dictionnaire de paire clé (string)- valeur (Nounours) privée mNounoursDico où Nounours est mutable + /// Comment encapsuler correctement un dictionnaire de ce type ? + /// Dans l'exemple suivant, nous voulons protéger le dictionnaire contre : + /// - les modifications du dictionnaire (ajout ou suppression d'éléments), + /// - la modification du dictionnaire lui-même (on ne doit pas pouvoir faire de new) + /// + /// En résumé, nous cherchons à rendre publique en lecture seule, le dictionnaire privé, en laissant chacun de ses éléments modifiables. + /// + /// La bonne solution consiste à : + /// - envelopper (wrapper) le dictionnaire privé avec un ReadOnlyDictionary construit dans le constructeur de MonLit. + /// - tant qu'en interne, dans la classe MonLit, on ne change pas la référence de mNounoursDico, le wrapper donne accès en lecture seule au dictionnaire + /// - attention de bien penser à le reconstruire si la référence change !!! + static void Main(string[] args) + { + MonLit monlit = new MonLit(); + + //lecture d'un nounours existant dans le dictionnaire : + var singe = monlit.Nounours["Singe"]; + WriteLine($"{singe.Nom} ({singe.DateDeNaissance.ToString("d")}, nbpoils : {singe.NbPoils})"); + + //tentative d'ajout d'un nouveau nounours : impossible, dictionnaire en lecture seule + //monlit.Nounours["Truite"] = new Nounours(3, "Truite", new System.DateTime(2013, 9, 3), 0); + + //les éléments ne sont pas immuables, mais c'est voulu, on peut donc les modifier + singe.NbPoils += 1000; + WriteLine($"{singe.Nom} ({singe.DateDeNaissance.ToString("d")}, nbpoils : {singe.NbPoils})"); + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/ex_023_018_ReadOnlyDictionaries.csproj b/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/ex_023_018_ReadOnlyDictionaries.csproj new file mode 100644 index 0000000..a88806a --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_018_ReadOnlyDictionaries/ex_023_018_ReadOnlyDictionaries.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_023_018_ReadOnlyDictionaries + Exe + ex_023_018_ReadOnlyDictionaries + 6.0.6 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/INounours.cs b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/INounours.cs new file mode 100644 index 0000000..239ae31 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/INounours.cs @@ -0,0 +1,43 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : INounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// +// ======================================================================== + +using System; + +namespace ex_023_019_ReadOnlyDictionary_and_values_dll +{ + /// + /// INounours est une façade immuable de Nounours : + /// Nounours est un type mutable interne, mais INounours n'offre accès publiquement qu'à des méthodes de lecture. + /// En accédant à la référence via le type INounours, elle aparaît immuable, en façade. + /// + public interface INounours + { + int Id + { + get; + } + + string Nom + { + get; + } + + DateTime DateDeNaissance + { + get; + } + + int NbPoils + { + get; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/MonLit.cs b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/MonLit.cs new file mode 100644 index 0000000..8085945 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/MonLit.cs @@ -0,0 +1,73 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MonLit.cs +// Author : Marc Chevaldonné +// Creation date : 2016-01-10 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace ex_023_019_ReadOnlyDictionary_and_values_dll +{ + /// + /// L'exemple suivant montre comment encapsuler un dictionnaire dans les cas suivants : + /// => les clés et/ou valeurs sont mutables, c'est-à-dire qu'on peut modifier leur état interne en appelant leurs méthodes ou propriétés + /// => MonLit possède un dictionnaire de paire clé (string)- valeur (Nounours) privée mNounoursDico où Nounours est mutable + /// Comment encapsuler correctement un dictionnaire de ce type ? + /// Dans l'exemple suivant, nous voulons protéger le dictionnaire contre : + /// - les modifications du dictionnaire (ajout ou suppression d'éléments), + /// - la modification du dictionnaire lui-même (on ne doit pas pouvoir faire de new) + /// - la modification de chaque valeur du dictionnaire : on ne doit pas pouvoir faire de new, ni appeler des méthodes ou propriétés mutables. + /// + /// En résumé, nous cherchons à rendre publique en lecture seule, le dictionnaire privé, tout en protégeant les valeurs. + /// + /// Il n'est pas possible d'utiliser une solution similaire à celle que nous avons utiliser pour les collections simples, + /// car les interfaces IDictionary ou IReadOnlyDictionary ne sont pas covariantes. + /// + /// La meilleure solution consiste à : + /// - rendre le type interne (Nounours) + /// c'est la raison pour laquelle cet exemple est sur deux assemblages : + /// . une bibliothèque de classes contenant le type interne et une classe contenant un dictionnaire privé avec ce type en valeur ; + /// . un exécutable consommant la classe contenant le dictionaire à encapsuler. + /// - faire une façade immuable publique de ce type (INounours) + /// cette façade immuable ne contient que des propriétés et méthodes en lecture seule + /// - utiliser un indexeur en lecture seule pour accéder aux valeurs du dictionnaire : + /// utilisez la clé dans l'indexeur + /// par exemple, pour encapsuler le dictionnaire Dictionary + /// utilisez un indexeur : public INounours this[string key] + /// soit dans le cas général, si vous voulez encapsuler le dictionaire privé : private Dictionary dico; + /// utilisez l'indexeur : public ITValue this[string key] => dico[key]; (où ITValue est une façade immuable de TValue) + /// dans ce cas, l'indexeur ne possède qu'un getteur, qui rend la valeur associée à la clé key, et castée en sa façade immuable (ITValue) + /// - on peut donner accès aux clés du dictionnaire en rendant une collection en lecture seule des clés. + /// + public class MonLit + { + //on veut encapsuler une collection d'un type muable + private Dictionary mNounoursDico = new Dictionary + { + ["Beluga"] = new Nounours(0, "Beluga", new DateTime(2012, 07, 29), 0), + ["Singe"] = new Nounours(1, "Singe", new DateTime(2009, 08, 09), 1345), + ["Girafe"] = new Nounours(2, "Girafe", new DateTime(2007, 11, 02), 567) + }; + + /// + /// indexeur permettant d'atteindre en lecture seule l'élément associé à la clé value + /// De plus, la valeur est castée automatiquement en façade immuable, ce qui la rendra immuable en dehors de la bibliothèque. + /// + /// + /// + public INounours this[string key] => mNounoursDico[key]; + + /// + /// pour permettre à l'utilisateur de parcourir les clés du dictionnaire + /// + public IReadOnlyCollection Keys => mNounoursDico.Keys; + + } +} diff --git a/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/Nounours.cs b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/Nounours.cs new file mode 100644 index 0000000..8ba0dd5 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/Nounours.cs @@ -0,0 +1,102 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// +// ======================================================================== + +using System; + +namespace ex_023_019_ReadOnlyDictionary_and_values_dll +{ + class Nounours : IEquatable, INounours + { + public int Id + { + get; + private set; + } + + public string Nom + { + get; + set; + } + + public DateTime DateDeNaissance + { + get; + private set; + } + + public int NbPoils + { + get; + set; + } + + public Nounours(int id, string nom, DateTime dateDeNaissance, int nbPoils) + { + Id = id; + Nom = nom; + DateDeNaissance = dateDeNaissance; + NbPoils = nbPoils; + } + + //... + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return (DateDeNaissance.Year * 1000 + DateDeNaissance.DayOfYear) * Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance.Equals(other.DateDeNaissance)); + } + + public override string ToString() + { + return $"{Nom} ({DateDeNaissance.ToString("d")} - nb de poils : {NbPoils})"; + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/ex_023_019_ReadOnlyDictionary_and_values_dll.csproj b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/ex_023_019_ReadOnlyDictionary_and_values_dll.csproj new file mode 100644 index 0000000..0c5a7e6 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_dll/ex_023_019_ReadOnlyDictionary_and_values_dll.csproj @@ -0,0 +1,11 @@ + + + netstandard2.0 + ex_023_019_ReadOnlyDictionary_and_values_dll + ex_023_019_ReadOnlyDictionary_and_values_dll + 1.6.0 + false + false + false + + diff --git a/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_exe/Program.cs b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_exe/Program.cs new file mode 100644 index 0000000..f0ca14e --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_exe/Program.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// +// ======================================================================== + +using ex_023_019_ReadOnlyDictionary_and_values_dll; +using System.Text; +using static System.Console; + +namespace ex_023_019_ReadOnlyDictionary_and_values_exe +{ + class Program + { + /// + /// L'exemple suivant montre comment encapsuler un dictionnaire dans les cas suivants : + /// => les clés et/ou valeurs sont mutables, c'est-à-dire qu'on peut modifier leur état interne en appelant leurs méthodes ou propriétés + /// => MonLit possède un dictionnaire de paire clé (string)- valeur (Nounours) privée mNounoursDico où Nounours est mutable + /// Comment encapsuler correctement un dictionnaire de ce type ? + /// Dans l'exemple suivant, nous voulons protéger le dictionnaire contre : + /// - les modifications du dictionnaire (ajout ou suppression d'éléments), + /// - la modification du dictionnaire lui-même (on ne doit pas pouvoir faire de new) + /// - la modification de chaque valeur du dictionnaire : on ne doit pas pouvoir faire de new, ni appeler des méthodes ou propriétés mutables. + /// + /// En résumé, nous cherchons à rendre publique en lecture seule, le dictionnaire privé, tout en protégeant les valeurs. + /// + /// Il n'est pas possible d'utiliser une solution similaire à celle que nous avons utiliser pour les collections simples, + /// car les interfaces IDictionary ou IReadOnlyDictionary ne sont pas covariantes. + /// + /// La meilleure solution consiste à : + /// - rendre le type interne (Nounours) + /// c'est la raison pour laquelle cet exemple est sur deux assemblages : + /// . une bibliothèque de classes contenant le type interne et une classe contenant un dictionnaire privé avec ce type en valeur ; + /// . un exécutable consommant la classe contenant le dictionaire à encapsuler. + /// - faire une façade immuable publique de ce type (INounours) + /// cette façade immuable ne contient que des propriétés et méthodes en lecture seule + /// - utiliser un indexeur en lecture seule pour accéder aux valeurs du dictionnaire : + /// utilisez la clé dans l'indexeur + /// par exemple, pour encapsuler le dictionnaire Dictionary + /// utilisez un indexeur : public INounours this[string key] + /// soit dans le cas général, si vous voulez encapsuler le dictionaire privé : private Dictionary dico; + /// utilisez l'indexeur : public ITValue this[string key] => dico[key]; (où ITValue est une façade immuable de TValue) + /// dans ce cas, l'indexeur ne possède qu'un getteur, qui rend la valeur associée à la clé key, et castée en sa façade immuable (ITValue) + /// - on peut donner accès aux clés du dictionnaire en rendant une collection en lecture seule des clés. + /// + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + MonLit monlit = new MonLit(); + + //on peut parcourir les clés du dictionnaire : + WriteLine("paires clé-valeur du dictionnaire"); + foreach (var key in monlit.Keys) + { + WriteLine($"\tclé : {key} ; valeur : {monlit[key]}"); + } + + + //tentatives de modification + // monlit["Singe"].Nom = "Beluga"; //impossible, car on utilise la façade immuable INounours + // monlit["Singe"] = monlit["Beluga"]; //impossible car l'indexeur est en lecture seule + } + } +} diff --git a/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_exe/ex_023_019_ReadOnlyDictionary_and_values_exe.csproj b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_exe/ex_023_019_ReadOnlyDictionary_and_values_exe.csproj new file mode 100644 index 0000000..d0e8372 --- /dev/null +++ b/p04_AdvancedCSharp/ex_023_019_ReadOnlyDictionary_and_values_exe/ex_023_019_ReadOnlyDictionary_and_values_exe.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_023_019_ReadOnlyDictionary_and_values_exe + Exe + ex_023_019_ReadOnlyDictionary_and_values_exe + 6.0.6 + false + false + false + + + + + diff --git a/p05_More_dotNet/ex_024_001_exceptions_Contexte/Program.cs b/p05_More_dotNet/ex_024_001_exceptions_Contexte/Program.cs new file mode 100644 index 0000000..3fad49b --- /dev/null +++ b/p05_More_dotNet/ex_024_001_exceptions_Contexte/Program.cs @@ -0,0 +1,35 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// +// ======================================================================== + +using static System.Console; + +namespace ex_024_001_exceptions_Contexte +{ + class Program + { + /// + /// Deux exemples d'exception lancée par le système + /// + /// + static void Main(string[] args) + { + //WriteLine("exemple d'exception gérée par le système : "); + //int a = 10, b = 0; + //int c = a / b; + //WriteLine("pas d'exception gérée"); + + WriteLine("exemple d'exception gérée par le système : "); + int[] tab = { 1, 2, 3 }; + int d = tab[3]; + WriteLine("pas d'exception gérée"); + } + } +} diff --git a/p05_More_dotNet/ex_024_001_exceptions_Contexte/ex_024_001_exceptions_Contexte.csproj b/p05_More_dotNet/ex_024_001_exceptions_Contexte/ex_024_001_exceptions_Contexte.csproj new file mode 100644 index 0000000..6acf49f --- /dev/null +++ b/p05_More_dotNet/ex_024_001_exceptions_Contexte/ex_024_001_exceptions_Contexte.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_024_001_exceptions_Contexte + Exe + ex_024_001_exceptions_Contexte + 6.0.6 + false + false + false + + diff --git a/p05_More_dotNet/ex_024_002_parse/Program.cs b/p05_More_dotNet/ex_024_002_parse/Program.cs new file mode 100644 index 0000000..86bf659 --- /dev/null +++ b/p05_More_dotNet/ex_024_002_parse/Program.cs @@ -0,0 +1,106 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// +// ======================================================================== + +using System; +using static System.Console; +using System.Linq; +using System.Text; + +namespace ex_024_002_parse +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + int n; + double d; + bool res; + + string choix = String.Empty; + string[] tabChoix = { "1", "2", "3" }; + + string s = String.Empty; + + while (!tabChoix.Contains(choix)) + { + Clear(); + WriteLine("Que voulez-vous faire ?"); + WriteLine("1. Entrer un entier ?"); + WriteLine("2. Entrer un réel en utilisant la culture de votre ordinateur ?"); + WriteLine(" (si votre windows est en français, la virgule s'écrit avec une , )"); + WriteLine("3. Entrer un réel avec la culture US ?"); + WriteLine(" (la virgule s'écrit avec un . )"); + choix = ReadLine(); + } + + Clear(); + + switch (choix) + { + case "1": + WriteLine("Entrez une chaîne de caractères, je vais tenter de la convertir en entier :"); + s = ReadLine(); + //1. Parse + //n = Int32.Parse(s); //lance une exception si Parse échoue + //2. TryParse : renvoie true si le Parse réussit, false s'il échoue + // le résultat est donné dans le paramètre de sortie + res = Int32.TryParse(s, out n); + if (res == true) + { + WriteLine(n); + } + else + { + WriteLine("conversion impossible"); + } + break; + + case "2": + WriteLine("Entrez une chaîne de caractères, je vais tenter de la convertir en réel en utilisant la culture actuelle :"); + s = ReadLine(); + //1. Parse + //d = Double.Parse(s); //lance une exception si Parse échoue + //2. TryParse : renvoie true si le Parse réussit, false s'il échoue + // le résultat est donné dans le paramètre de sortie + res = Double.TryParse(s, out d); + if (res == true) + { + WriteLine(d); + } + else + { + WriteLine("conversion impossible"); + } + break; + + case "3": + WriteLine("Entrez une chaîne de caractères, je vais tenter de la convertir en réel en utilisant la culture US :"); + s = ReadLine(); + //1. Parse + //d = Double.Parse(s); //lance une exception si Parse échoue + //2. TryParse : renvoie true si le Parse réussit, false s'il échoue + // le résultat est donné dans le paramètre de sortie + res = Double.TryParse(s, System.Globalization.NumberStyles.Number, new System.Globalization.CultureInfo("en-US"), out d); + if (res == true) + { + WriteLine(d); + } + else + { + WriteLine("conversion impossible"); + } + break; + } + } + } +} diff --git a/p05_More_dotNet/ex_024_002_parse/ex_024_002_parse.csproj b/p05_More_dotNet/ex_024_002_parse/ex_024_002_parse.csproj new file mode 100644 index 0000000..c607852 --- /dev/null +++ b/p05_More_dotNet/ex_024_002_parse/ex_024_002_parse.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_024_002_parse + Exe + ex_024_002_parse + 6.0.6 + false + false + false + + diff --git a/p05_More_dotNet/ex_024_003_exceptions/Program.cs b/p05_More_dotNet/ex_024_003_exceptions/Program.cs new file mode 100644 index 0000000..d9f03d2 --- /dev/null +++ b/p05_More_dotNet/ex_024_003_exceptions/Program.cs @@ -0,0 +1,75 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-01 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_024_003_exceptions +{ + class Program + { + static void Main(string[] args) + { + //exemple 1 + try + { + WriteLine("avant division : "); + int a = 10, b = 0; + int c = a / b; + WriteLine("après division"); + } + catch (Exception exc) + { + WriteLine("erreur de division par 0"); + } + + //exemple 2 + try + { + WriteLine("avant d'accéder au tableau"); + int[] tab = { 1, 2, 3 }; + int d = tab[3]; + WriteLine("après"); + } + catch (Exception exc) + { + WriteLine("erreur d'accès au tableau"); + } + + //exemple 3 : on peut catcher des exceptions différentes en spécifiant la classe d'exception + try + { + WriteLine("début"); + int[] tab = { 1, 2, 3 }; + int a = 10, b = 1; + tab[3] = a / b; + WriteLine("après"); + } + + catch (ArithmeticException exc) + { + WriteLine("erreur sur opération arithmétique"); + } + catch (IndexOutOfRangeException exc) + { + WriteLine("erreur d'accès à un tableau"); + } + catch (Exception exc) + { + WriteLine("je crois que nous avons un problème"); + } + finally + { + WriteLine("fin des tests"); + } + } + } +} diff --git a/p05_More_dotNet/ex_024_003_exceptions/ex_024_003_exceptions.csproj b/p05_More_dotNet/ex_024_003_exceptions/ex_024_003_exceptions.csproj new file mode 100644 index 0000000..6fe2b8e --- /dev/null +++ b/p05_More_dotNet/ex_024_003_exceptions/ex_024_003_exceptions.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_024_003_exceptions + Exe + ex_024_003_exceptions + 6.0.6 + false + false + false + + diff --git a/p05_More_dotNet/ex_024_004_propagation_exceptions/Program.cs b/p05_More_dotNet/ex_024_004_propagation_exceptions/Program.cs new file mode 100644 index 0000000..4d892fb --- /dev/null +++ b/p05_More_dotNet/ex_024_004_propagation_exceptions/Program.cs @@ -0,0 +1,109 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-02 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.Text; +using static System.Console; + +namespace ex_024_004_exceptions +{ + /// + /// cet exemple montre comment lancer une exception depuis une méthode pour quelle puisse être attrapée par l'appelant + /// Vous pouvez lancer le programme en rentrant les deux suites de nombres suivantes : + /// A. 1,2,3 et vous obtiendrez une IndexOutOfRangeException + /// B. 1,0,2 et vous obtiendrez une ArithmeticException + /// + /// 1. on rentre dans le bloc try du Main + /// 2. à l'intérieur, fonction() est appelé + /// 3. on rentre dans le bloc try de fonction() + /// 4. une exception est lancée + /// 5. on sort du bloc try de fonction() + /// 6. on rentre dans le bloc catch correspondant à l'exception lancée dans fonction() + /// 7a. si vous rentrez dans catch (IndexOutOfRangeException), il n'y a pas de propagation + /// 7b. si vous rentrez dans catch (ArithmeticException), celui-ci propage l'exception en la lançant avec : throw new ArithmeticException(); + /// 8. on sort du bloc catch de fonction() + /// 9. on exécute le bloc finally dans fonction() (celui-ci est toujours exécuté à la fin d'un try, même s'il n'y a pas d'exception) + /// 10. on sort de fonction() + /// 11a. si vous avez eu IndexOutOfRangeException, comme il n'y a pas eu de propagation, le reste du try du Main s'exécute normalement, puis le bloc finally + /// 11b. si vous avez eu ArithmeticException, comme il y a eu propagation, vous vous retrouvez dans le bloc catch(ArithmeticException), puis le bloc finally + /// + /// + class Program + { + /// + /// une fonction qui fait des trucs et qui peut lancer une exception + /// + /// il est conseillé de rajouter une balise "exception" dans les commentaires de la fonction pour préciser qu'elle peut être lancée + /// et hop + static void fonction() + { + WriteLine("soit : int[] tab = { 1, 2, 3 };"); + WriteLine("nous allons calculer : tab[c] = a / b;"); + WriteLine("vous pouvez tester des exceptions en rentrant b = 0, ou c en dehors des limites du tableau."); + WriteLine("Rentrez a :"); + string s1 = ReadLine(); + WriteLine("Rentrez b :"); + string s2 = ReadLine(); + WriteLine("Rentrez c :"); + string s3 = ReadLine(); + Int32.TryParse(s1, out var a); + Int32.TryParse(s2, out var b); + Int32.TryParse(s3, out var c); + int[] tab = { 1, 2, 3 }; + try + { + WriteLine("début du try de fonction"); + tab[c] = a / b; + WriteLine("fin du groupe try de fonction"); + } + + //mettez ou enlevez les commentaires sur les catch pour voir les différences de résultats + catch (ArithmeticException) + { + WriteLine("ArithmeticException dans fonction"); + throw new ArithmeticException(); + } + catch (IndexOutOfRangeException) + { + WriteLine("IndexOutOfRangeException dans fonction"); + } + finally + { + WriteLine("finally dans fonction"); + } + } + + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + try + { + WriteLine("début du try de Main"); + fonction(); + WriteLine("fin du groupe try de Main"); + } + catch (ArithmeticException) + { + WriteLine("ArithmeticException dans Main"); + } + catch (IndexOutOfRangeException) + { + WriteLine("IndexOutOfRangeException dans Main"); + } + finally + { + WriteLine("finally dans Main"); + } + } + } +} diff --git a/p05_More_dotNet/ex_024_004_propagation_exceptions/ex_024_004_propagation_exceptions.csproj b/p05_More_dotNet/ex_024_004_propagation_exceptions/ex_024_004_propagation_exceptions.csproj new file mode 100644 index 0000000..4804b10 --- /dev/null +++ b/p05_More_dotNet/ex_024_004_propagation_exceptions/ex_024_004_propagation_exceptions.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_024_004_propagation_exceptions + Exe + ex_024_004_propagation_exceptions + 6.0.6 + false + false + false + + diff --git a/p05_More_dotNet/ex_024_005_exceptions_personnalisees/Program.cs b/p05_More_dotNet/ex_024_005_exceptions_personnalisees/Program.cs new file mode 100644 index 0000000..1b4f025 --- /dev/null +++ b/p05_More_dotNet/ex_024_005_exceptions_personnalisees/Program.cs @@ -0,0 +1,60 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2019-12-08 +// +// ======================================================================== + +using System; +using System.Text; +using static System.Console; + +namespace ex_024_005_exceptions_personnalisees +{ + /// + /// ma classe d'exception + /// + class MyException : Exception + { + public MyException(string msg) : base(msg) { } + } + + /// + /// programme utilisant une exception personnalisée si les deux noms rentrés par les joueurs sont les mêmes + /// + class Program + { + static void GetPlayerNames() + { + WriteLine("Cet exemple permet de lancer une exception personnalisée si les deux noms rentrés sont les mêmes."); + WriteLine("Rentrez le nom du premier joueur"); + string player1 = ReadLine(); + WriteLine("Rentrez le nom du deuxième joueur"); + string player2 = ReadLine(); + + if (player1 == player2) + { + throw new MyException($"Les deux joueurs s'appellent {player1}. Ils doivent avoir des noms différents"); + } + } + + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + try + { + GetPlayerNames(); + } + catch (MyException exc) + { + WriteLine(exc.Message); + } + WriteLine("pas de jeu en fait..."); + } + } +} diff --git a/p05_More_dotNet/ex_024_005_exceptions_personnalisees/ex_024_005_exceptions_personnalisees.csproj b/p05_More_dotNet/ex_024_005_exceptions_personnalisees/ex_024_005_exceptions_personnalisees.csproj new file mode 100644 index 0000000..8d828a9 --- /dev/null +++ b/p05_More_dotNet/ex_024_005_exceptions_personnalisees/ex_024_005_exceptions_personnalisees.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_024_005_exceptions_personnalisees + Exe + ex_024_005_exceptions_personnalisees + 6.0.6 + false + false + false + + diff --git a/p05_More_dotNet/ex_025_001_DebugTrace/Program.cs b/p05_More_dotNet/ex_025_001_DebugTrace/Program.cs new file mode 100644 index 0000000..e9afbcb --- /dev/null +++ b/p05_More_dotNet/ex_025_001_DebugTrace/Program.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-02 +// +// ======================================================================== + +using System; +using static System.Console; + +using System.Diagnostics; +using System.Text; + +namespace ex_025_001_DebugTrace +{ + //Note : pour utiliser Trace, il faut rajouter la référence system.diagnostics.TraceSource + //Note : pour utiliser TextWriterTracerListener, il faut rajouter la référence system.diagnostics.textwritertracelistener + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + //à partir d'ici, tous les messages de Debug et Trace sont affichés dans la fenêtre de sortie, + //si et seulement si vous exécutez le programme avec F5 ou Déboguer > Démarrer le débogage + int a = 2; + int b = 3; + int c = -4; + + int d = a + b; + //la ligne suivante ne sera gardée à la compilation que si le symbole DEBUG est défini. + DisplayMessage("d vaut " + d); + + //les lignes suivantes sont exécutées si le symbole DEBUG est défini (par défaut en mode Debug) + //et le contenu est affiché dans la fenêtre de Sortie + //(généralement en bas de l'écran) + Debug.WriteLine("d vaut " + d); + Debug.WriteLineIf(d > c, "d est supérieur à c"); + + int e = d * c; + //les lignes suivantes sont exécutées si le symbole TRACE est défini (par défaut en mode Debug et Release) + //et le contenu est généralement affiché en bas de l'écran dans la fenêtre de Sortie + Trace.TraceInformation("e = " + e); + Trace.TraceWarning("e vaut : " + e); + + //le texte est affiché dans la fenêtre de sortie, si et seulement si le symbole DEBUG est défini et si la condition "e>0" est vraie + //Debug.Assert(e > 0, "e est négatif !"); + + //dans les lignes suivantes, nous demandons à la classe Trace de ne plus écrire dans la fenêtre de Sortie... + Trace.Listeners.Clear(); + //...on lui définit un nouveau TraceListener qui sera la fenêtre Console... + //les messages de Debug et Trace seront donc désormais affichés dans la Console + System.IO.TextWriter tw = Console.Out; + Trace.Listeners.Add(new TextWriterTraceListener(tw)); + //...les messages de Trace sont donc maintenant envoyés dans la Console + Trace.Assert(e > 0, "e est négatif !"); + if (e < 0) + { + Trace.Fail("e est négatif"); + } + + } + + /// + /// cette méthode et les appels de cette méthode ne seront gardés à la compilation, que si le symbole DEBUG est défini. + /// Le symbole DEBUG est défini par défaut en mode ... Debug + /// + /// + [Conditional("DEBUG")] + static void DisplayMessage(string message) + { + WriteLine(message); + } + } +} diff --git a/p05_More_dotNet/ex_025_001_DebugTrace/ex_025_001_DebugTrace.csproj b/p05_More_dotNet/ex_025_001_DebugTrace/ex_025_001_DebugTrace.csproj new file mode 100644 index 0000000..2fd76c1 --- /dev/null +++ b/p05_More_dotNet/ex_025_001_DebugTrace/ex_025_001_DebugTrace.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_025_001_DebugTrace + Exe + ex_025_001_DebugTrace + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Carré.cs b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Carré.cs new file mode 100644 index 0000000..ab0a67e --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Carré.cs @@ -0,0 +1,21 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Carré.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_001_intro_avec_interfaces +{ + class Carré : IModifieur + { + public int Modifier(int nombreAModifier) + { + return nombreAModifier * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Cube.cs b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Cube.cs new file mode 100644 index 0000000..b517a76 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Cube.cs @@ -0,0 +1,21 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Cube.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_001_intro_avec_interfaces +{ + class Cube : IModifieur + { + public int Modifier(int nombreAModifier) + { + return nombreAModifier * nombreAModifier * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Droite.cs b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Droite.cs new file mode 100644 index 0000000..c3d2e02 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Droite.cs @@ -0,0 +1,39 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Droite.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_001_intro_avec_interfaces +{ + class Droite : IModifieur + { + public int Offset + { + get; + private set; + } + + public int Pente + { + get; + private set; + } + + public Droite(int offset, int pente) + { + Offset = offset; + Pente = pente; + } + + public int Modifier(int nombreAModifier) + { + return Offset + Pente * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/IModifieur.cs b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/IModifieur.cs new file mode 100644 index 0000000..1587a1f --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/IModifieur.cs @@ -0,0 +1,18 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : IModifieur.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_001_intro_avec_interfaces +{ + public interface IModifieur + { + int Modifier(int nombreAModifier); + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Program.cs b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Program.cs new file mode 100644 index 0000000..59ee879 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/Program.cs @@ -0,0 +1,38 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; + +namespace ex_028_001_intro_avec_interfaces +{ + class Program : IModifieur + { + static void Main(string[] args) + { + IModifieur m = new Program(); + WriteLine(m.Modifier(5)); + + m = new Carré(); + WriteLine(m.Modifier(5)); + + m = new Cube(); + WriteLine(m.Modifier(5)); + + m = new Droite(2, 3); + WriteLine(m.Modifier(5)); + } + + public int Modifier(int nombreAModifier) + { + return 2 * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/ex_028_001_intro_avec_interfaces.csproj b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/ex_028_001_intro_avec_interfaces.csproj new file mode 100644 index 0000000..9187dde --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_001_intro_avec_interfaces/ex_028_001_intro_avec_interfaces.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_001_intro_avec_interfaces + Exe + ex_028_001_intro_avec_interfaces + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/Droite.cs b/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/Droite.cs new file mode 100644 index 0000000..0c10407 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/Droite.cs @@ -0,0 +1,51 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Droite.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace Namespace2 +{ + /// + /// classe représentant une droite + /// + public class Droite + { + /// + /// valeur du point d'abscisse nul de la droite + /// + int mOffset; + + /// + /// coefficient directeur de la droite + /// + int mPente; + + /// + /// constructeur de la droite + /// + /// valeur du point d'abscisse nul + /// coefficient directeur de la droite + public Droite(int offset, int pente) + { + mOffset = offset; + mPente = pente; + } + + /// + /// calcul l'ordonnée d'un point de la droite à partir de son abscisse + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué. + /// + /// abscisse du point + /// ordonnée du point sur la droite + public int Image(int a) + { + return mOffset + mPente * a; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/MaClasseDeMaths.cs b/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/MaClasseDeMaths.cs new file mode 100644 index 0000000..3a7c238 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/MaClasseDeMaths.cs @@ -0,0 +1,56 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MaClasseDeMath.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace Namespace2 +{ + /// + /// une classe qui réalise quelques opérations mathématiques + /// + public static class MaClasseDeMaths + { + /// + /// méthode static calculant a^b + /// Cette méthode n'est pas de type "Modifieur" car elle n'a pas la même signature que le délégué + /// + /// l'entier a élévé à la puissance b + /// l'exposant + /// a^b + public static int Power(int a, int b) + { + return (int)Math.Pow(a, b); + } + + /// + /// méthode calculant le carré d'un entier + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué + /// + /// entier élevé au carré + /// a^2 + public static int Carré(int a) + { + return a * a; + } + + /// + /// méthode calculant le cube d'un entier + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué + /// + /// entier élevé au cube + /// a^3 + public static int Cube(int a) + { + return a * a * a; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/Program.cs b/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/Program.cs new file mode 100644 index 0000000..cad364b --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/Program.cs @@ -0,0 +1,131 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; +using Namespace2; +using System.Text; + +namespace Namespace1 +{ + /// + /// le délégué + /// Toutes les méthodes qui voudront être des "instances déléguées" de ce "type délégué" + /// devront avoir la même signature, soit ici : prendre un entier en paramètre et rendre un entier. + /// + /// un entier + /// un autre entier dépendant du paramètre et de l'exécution de la fonction de type Modifieur + delegate int Modifieur(int x); + + class Program + { + /// + /// méthode prenant en paramètre un type délégué ("Modifieur") + /// On peut donc utiliser dans cette méthode, n'importe quelle méthode ayant la signature du délégué. + /// + /// tableau de nombres à modifier + /// instance déléguée qui sera utilisée dans la méthode Modifie + static void Modifie(int[] nombres, Modifieur m) + { + for (int i = 0; i < nombres.Length; i++) + { + //ici on utilise l'instance délégué pour cette instruction + nombres[i] = m(nombres[i]); + } + } + + /// + /// ici, on a une méthode de type "Modifieur" (le délégué au-dessus) + /// et on l'utilise comme type de méthode dans la signature d'une méthode (Modifie juste au-dessus). + /// + /// + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("int[] tab = { 1, 2, 3, 4 };"); + ForegroundColor = ConsoleColor.White; + #endregion + int[] tab = { 1, 2, 3, 4 }; + #region Affichage des infos dans la Console + foreach (int i in tab) + { + Write($"{i} "); + } + WriteLine(); + WriteLine(); + #endregion + + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("Modifie(tab, MaClasseDeMaths.Carré);"); + ForegroundColor = ConsoleColor.White; + #endregion + Modifieur n = MaClasseDeMaths.Carré; + Modifie(tab, n); + #region Affichage des infos dans la Console + foreach (int i in tab) + { + Write($"{i} "); + } + WriteLine(); + WriteLine(); + #endregion + + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("Modifie(tab, Double);"); + ForegroundColor = ConsoleColor.White; + #endregion + Modifie(tab, Double); + #region Affichage des infos dans la Console + foreach (int i in tab) + { + Write($"{i} "); + } + WriteLine(); + WriteLine(); + #endregion + + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("Modifie(tab, Droite.Image);"); + ForegroundColor = ConsoleColor.White; + #endregion + Droite droite = new Droite(1, 2); + Modifie(tab, droite.Image); + #region Affichage des infos dans la Console + foreach (int i in tab) + { + Write($"{i} "); + } + WriteLine(); + WriteLine(); + #endregion + + } + + /// + /// méthode static de type "Modifieur" car elle a la même signature que le délégué Modifieur + /// + /// un entier + /// le double de l'entier pris en paramètre + static int Double(int x) + { + return x * 2; + } + + + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/ex_028_002_intro_avec_delegate.csproj b/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/ex_028_002_intro_avec_delegate.csproj new file mode 100644 index 0000000..601b29e --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_002_intro_avec_delegate/ex_028_002_intro_avec_delegate.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_002_intro_avec_delegate + Exe + ex_028_002_intro_avec_delegate + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Carré.cs b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Carré.cs new file mode 100644 index 0000000..b4c0c45 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Carré.cs @@ -0,0 +1,21 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Carré.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_003_interface_as_parameter +{ + class Carré : IModifieur + { + public int Modifier(int nombreAModifier) + { + return nombreAModifier * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Cube.cs b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Cube.cs new file mode 100644 index 0000000..ea2c98d --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Cube.cs @@ -0,0 +1,21 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Cube.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_003_interface_as_parameter +{ + class Cube : IModifieur + { + public int Modifier(int nombreAModifier) + { + return nombreAModifier * nombreAModifier * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Droite.cs b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Droite.cs new file mode 100644 index 0000000..1ac1837 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Droite.cs @@ -0,0 +1,39 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Droite.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_003_interface_as_parameter +{ + class Droite : IModifieur + { + public int Offset + { + get; + private set; + } + + public int Pente + { + get; + private set; + } + + public Droite(int offset, int pente) + { + Offset = offset; + Pente = pente; + } + + public int Modifier(int nombreAModifier) + { + return Offset + Pente * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/IModifieur.cs b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/IModifieur.cs new file mode 100644 index 0000000..e38e777 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/IModifieur.cs @@ -0,0 +1,18 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : IModifieur.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_003_interface_as_parameter +{ + public interface IModifieur + { + int Modifier(int nombreAModifier); + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Program.cs b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Program.cs new file mode 100644 index 0000000..8b1f688 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/Program.cs @@ -0,0 +1,67 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; + +namespace ex_028_003_interface_as_parameter +{ + class Program : IModifieur + { + static void Main(string[] args) + { + int[] tableau = { 1, 2, 3, 4, 5 }; + IModifieur m = new Program(); + Modifie(tableau, m); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + m = new Carré(); + Modifie(tableau, m); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + m = new Cube(); + Modifie(tableau, m); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + m = new Droite(2, 3); + Modifie(tableau, m); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + } + + public int Modifier(int nombreAModifier) + { + return 2 * nombreAModifier; + } + + public static void Modifie(int[] tab, IModifieur mod) + { + for (int i = 0; i < tab.Length; i++) + { + tab[i] = mod.Modifier(tab[i]); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/ex_028_003_interface_as_parameter.csproj b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/ex_028_003_interface_as_parameter.csproj new file mode 100644 index 0000000..3ec5952 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_003_interface_as_parameter/ex_028_003_interface_as_parameter.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_003_interface_as_parameter + Exe + ex_028_003_interface_as_parameter + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/Droite.cs b/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/Droite.cs new file mode 100644 index 0000000..0c10407 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/Droite.cs @@ -0,0 +1,51 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Droite.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace Namespace2 +{ + /// + /// classe représentant une droite + /// + public class Droite + { + /// + /// valeur du point d'abscisse nul de la droite + /// + int mOffset; + + /// + /// coefficient directeur de la droite + /// + int mPente; + + /// + /// constructeur de la droite + /// + /// valeur du point d'abscisse nul + /// coefficient directeur de la droite + public Droite(int offset, int pente) + { + mOffset = offset; + mPente = pente; + } + + /// + /// calcul l'ordonnée d'un point de la droite à partir de son abscisse + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué. + /// + /// abscisse du point + /// ordonnée du point sur la droite + public int Image(int a) + { + return mOffset + mPente * a; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/MaClasseDeMaths.cs b/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/MaClasseDeMaths.cs new file mode 100644 index 0000000..3a7c238 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/MaClasseDeMaths.cs @@ -0,0 +1,56 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MaClasseDeMath.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace Namespace2 +{ + /// + /// une classe qui réalise quelques opérations mathématiques + /// + public static class MaClasseDeMaths + { + /// + /// méthode static calculant a^b + /// Cette méthode n'est pas de type "Modifieur" car elle n'a pas la même signature que le délégué + /// + /// l'entier a élévé à la puissance b + /// l'exposant + /// a^b + public static int Power(int a, int b) + { + return (int)Math.Pow(a, b); + } + + /// + /// méthode calculant le carré d'un entier + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué + /// + /// entier élevé au carré + /// a^2 + public static int Carré(int a) + { + return a * a; + } + + /// + /// méthode calculant le cube d'un entier + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué + /// + /// entier élevé au cube + /// a^3 + public static int Cube(int a) + { + return a * a * a; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/Program.cs b/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/Program.cs new file mode 100644 index 0000000..b5852bf --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/Program.cs @@ -0,0 +1,131 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; +using Namespace2; +using System.Text; + +namespace Namespace1 +{ + /// + /// le délégué + /// Toutes les méthodes qui voudront être des "instances déléguées" de ce "type délégué" + /// devront avoir la même signature, soit ici : prendre un entier en paramètre et rendre un entier. + /// + /// un entier + /// un autre entier dépendant du paramètre et de l'exécution de la fonction de type Modifieur + delegate int Modifieur(int x); + + class Program + { + /// + /// méthode prenant en paramètre un type délégué ("Modifieur") + /// On peut donc utiliser dans cette méthode, n'importe quelle méthode ayant la signature du délégué. + /// + /// tableau de nombres à modifier + /// instance déléguée qui sera utilisée dans la méthode Modifie + static void Modifie(int[] nombres, Modifieur m) + { + for (int i = 0; i < nombres.Length; i++) + { + //ici on utilise l'instance délégué pour cette instruction + nombres[i] = m(nombres[i]); + } + } + + /// + /// ici, on a une méthode de type "Modifieur" (le délégué au-dessus) + /// et on l'utilise comme type de méthode dans la signature d'une méthode (Modifie juste au-dessus). + /// + /// + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("int[] tab = { 1, 2, 3, 4 };"); + ForegroundColor = ConsoleColor.White; + #endregion + int[] tab = { 1, 2, 3, 4 }; + #region Affichage des infos dans la Console + foreach (int i in tab) + { + Write($"{i} "); + } + WriteLine(); + WriteLine(); + #endregion + + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("Modifie(tab, MaClasseDeMaths.Carré);"); + ForegroundColor = ConsoleColor.White; + #endregion + Modifieur n = MaClasseDeMaths.Carré; + Modifie(tab, n); + #region Affichage des infos dans la Console + foreach (int i in tab) + { + Write($"{i} "); + } + WriteLine(); + WriteLine(); + #endregion + + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("Modifie(tab, Double);"); + ForegroundColor = ConsoleColor.White; + #endregion + Modifie(tab, Double); + #region Affichage des infos dans la Console + foreach (int i in tab) + { + Write($"{i} "); + } + WriteLine(); + WriteLine(); + #endregion + + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("Modifie(tab, Droite.Image);"); + ForegroundColor = ConsoleColor.White; + #endregion + Droite droite = new Droite(1, 2); + Modifie(tab, droite.Image); + #region Affichage des infos dans la Console + foreach (int i in tab) + { + Write($"{i} "); + } + WriteLine(); + WriteLine(); + #endregion + + } + + /// + /// méthode static de type "Modifieur" car elle a la même signature que le délégué Modifieur + /// + /// un entier + /// le double de l'entier pris en paramètre + static int Double(int x) + { + return x * 2; + } + + + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/ex_028_004_delegate_as_parameter.csproj b/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/ex_028_004_delegate_as_parameter.csproj new file mode 100644 index 0000000..07362e0 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_004_delegate_as_parameter/ex_028_004_delegate_as_parameter.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_004_delegate_as_parameter + Exe + ex_028_004_delegate_as_parameter + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/Droite.cs b/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/Droite.cs new file mode 100644 index 0000000..0c10407 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/Droite.cs @@ -0,0 +1,51 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Droite.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace Namespace2 +{ + /// + /// classe représentant une droite + /// + public class Droite + { + /// + /// valeur du point d'abscisse nul de la droite + /// + int mOffset; + + /// + /// coefficient directeur de la droite + /// + int mPente; + + /// + /// constructeur de la droite + /// + /// valeur du point d'abscisse nul + /// coefficient directeur de la droite + public Droite(int offset, int pente) + { + mOffset = offset; + mPente = pente; + } + + /// + /// calcul l'ordonnée d'un point de la droite à partir de son abscisse + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué. + /// + /// abscisse du point + /// ordonnée du point sur la droite + public int Image(int a) + { + return mOffset + mPente * a; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/MaClasseDeMaths.cs b/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/MaClasseDeMaths.cs new file mode 100644 index 0000000..164d5ac --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/MaClasseDeMaths.cs @@ -0,0 +1,63 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MaClasseDeMath.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace Namespace2 +{ + /// + /// une classe qui réalise quelques opérations mathématiques + /// + public class MaClasseDeMaths + { + /// + /// on définit le délégué ici dans la classe MaClasseDeMath avec la visibilité qui nous intéresse (ici j'ai choisi internal) + /// + /// un entier + /// un autre entier dépendant du paramètre et de l'exécution de la fonction de type Modifieur + internal delegate int Modifieur(int x); + + /// + /// méthode static calculant a^b + /// Cette méthode n'est pas de type "Modifieur" car elle n'a pas la même signature que le délégué + /// + /// l'entier a élévé à la puissance b + /// l'exposant + /// a^b + public static int Power(int a, int b) + { + return (int)Math.Pow(a, b); + } + + /// + /// méthode calculant le carré d'un entier + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué + /// + /// entier élevé au carré + /// a^2 + public static int Carré(int a) + { + return a * a; + } + + /// + /// méthode calculant le cube d'un entier + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué + /// + /// entier élevé au cube + /// a^3 + public static int Cube(int a) + { + return a * a * a; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/Program.cs b/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/Program.cs new file mode 100644 index 0000000..8cf8445 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/Program.cs @@ -0,0 +1,125 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; + +using Namespace2; +using System.Text; + +namespace Namespace1 +{ + class Program + { + + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + //on déclare une instance d'un type délégué déclaré dans une autre classe, le reste fonctionne pareil + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.White; + Write("utilisation d'une méthode "); + ForegroundColor = ConsoleColor.Magenta; + Write("statique "); + ForegroundColor = ConsoleColor.White; + Write("comme instance de délégué d'un type délégué d'une autre classe : "); + ForegroundColor = ConsoleColor.Red; + WriteLine("Double"); + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("MaClasseDeMath.Modifieur m = Double;"); + WriteLine("int resultat = m(3)"); + ForegroundColor = ConsoleColor.Red; + #endregion + MaClasseDeMaths.Modifieur m = Double; + int resultat = m(3); + WriteLine("m(3) = " + resultat); + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGray; + #endregion + WriteLine($"m.Target == null ? {m.Target == null}"); + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.White; + WriteLine(); + #endregion + + + + //on affecte MaClasseDeMath.Carré (méthode static d'une autre classe que Main) à m + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.White; + Write("utilisation d'une méthode "); + ForegroundColor = ConsoleColor.Magenta; + Write("statique d'une autre classe "); + ForegroundColor = ConsoleColor.White; + Write("comme instance de délégué d'un type délégué d'une autre classe : "); + ForegroundColor = ConsoleColor.Red; + WriteLine("MaClasseDeMath.Carré"); + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("MaClasseDeMath.Modifieur m = MaClasseDeMath.Carré;"); + WriteLine("int resultat = m(3)"); + ForegroundColor = ConsoleColor.Red; + #endregion + m = MaClasseDeMaths.Carré; + resultat = m(3); + WriteLine($"m(3) = {resultat}"); + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGray; + #endregion + WriteLine($"m.Target == null ? {m.Target == null}"); + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.White; + WriteLine(); + #endregion + + //on affecte Droite.Image (méthode non static d'une autre classe que Main) à m + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.White; + Write("utilisation d'une méthode "); + ForegroundColor = ConsoleColor.Magenta; + Write("non statique d'une autre classe "); + ForegroundColor = ConsoleColor.White; + Write("comme instance de délégué d'un type délégué d'une autre classe : "); + ForegroundColor = ConsoleColor.Red; + WriteLine("Droite.Image"); + ForegroundColor = ConsoleColor.DarkGreen; + WriteLine("Droite droite = new Droite(1, 2);"); + WriteLine("MaClasseDeMath.Modifieur m = droite.Image;"); + WriteLine("int resultat = m(3)"); + ForegroundColor = ConsoleColor.Red; + #endregion + Droite droite = new Droite(1, 2); + m = droite.Image; + resultat = m(3); + WriteLine($"m(3) = {resultat}"); + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.DarkGray; + #endregion + WriteLine($"m.Target == null ? {m.Target == null}"); + WriteLine($"m.Target : {m.Target}"); + #region Affichage des infos dans la Console + ForegroundColor = ConsoleColor.White; + WriteLine(); + #endregion + } + + /// + /// méthode static de type "Modifieur" car elle a la même signature que le délégué Modifieur + /// + /// un entier + /// le double de l'entier pris en paramètre + static int Double(int x) + { + return x * 2; + } + } + +} diff --git a/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/ex_028_005_nested_delegate.csproj b/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/ex_028_005_nested_delegate.csproj new file mode 100644 index 0000000..880b35d --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_005_nested_delegate/ex_028_005_nested_delegate.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_005_nested_delegate + Exe + ex_028_005_nested_delegate + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Carré.cs b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Carré.cs new file mode 100644 index 0000000..ac7eca6 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Carré.cs @@ -0,0 +1,21 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Carré.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_006_Strategy_et_interface +{ + class Carré : IModifieur + { + public int Modifier(int nombreAModifier) + { + return nombreAModifier * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Cube.cs b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Cube.cs new file mode 100644 index 0000000..5d69f3a --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Cube.cs @@ -0,0 +1,21 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Cube.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_006_Strategy_et_interface +{ + class Cube : IModifieur + { + public int Modifier(int nombreAModifier) + { + return nombreAModifier * nombreAModifier * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Droite.cs b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Droite.cs new file mode 100644 index 0000000..6a03bb7 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Droite.cs @@ -0,0 +1,39 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Droite.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_006_Strategy_et_interface +{ + class Droite : IModifieur + { + public int Offset + { + get; + private set; + } + + public int Pente + { + get; + private set; + } + + public Droite(int offset, int pente) + { + Offset = offset; + Pente = pente; + } + + public int Modifier(int nombreAModifier) + { + return Offset + Pente * nombreAModifier; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/IModifieur.cs b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/IModifieur.cs new file mode 100644 index 0000000..c9b13e5 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/IModifieur.cs @@ -0,0 +1,18 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : IModifieur.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_006_Strategy_et_interface +{ + public interface IModifieur + { + int Modifier(int nombreAModifier); + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Program.cs b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Program.cs new file mode 100644 index 0000000..4c874fa --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/Program.cs @@ -0,0 +1,63 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; + +namespace ex_028_006_Strategy_et_interface +{ + class Program + { + IModifieur mModifieur; + + public Program(IModifieur modifieur) + { + mModifieur = modifieur; + } + + public void Modifie(int[] tab) + { + for (int i = 0; i < tab.Length; i++) + { + tab[i] = mModifieur.Modifier(tab[i]); + } + } + + static void Main(string[] args) + { + int[] tableau = { 1, 2, 3, 4, 5 }; + Program p = new Program(new Carré()); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + p = new Program(new Cube()); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + p = new Program(new Droite(2, 3)); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + } + + + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/ex_028_006_Strategy_et_interface.csproj b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/ex_028_006_Strategy_et_interface.csproj new file mode 100644 index 0000000..537397f --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_006_Strategy_et_interface/ex_028_006_Strategy_et_interface.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_006_Strategy_et_interface + Exe + ex_028_006_Strategy_et_interface + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/Droite.cs b/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/Droite.cs new file mode 100644 index 0000000..0c10407 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/Droite.cs @@ -0,0 +1,51 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Droite.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace Namespace2 +{ + /// + /// classe représentant une droite + /// + public class Droite + { + /// + /// valeur du point d'abscisse nul de la droite + /// + int mOffset; + + /// + /// coefficient directeur de la droite + /// + int mPente; + + /// + /// constructeur de la droite + /// + /// valeur du point d'abscisse nul + /// coefficient directeur de la droite + public Droite(int offset, int pente) + { + mOffset = offset; + mPente = pente; + } + + /// + /// calcul l'ordonnée d'un point de la droite à partir de son abscisse + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué. + /// + /// abscisse du point + /// ordonnée du point sur la droite + public int Image(int a) + { + return mOffset + mPente * a; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/MaClasseDeMaths.cs b/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/MaClasseDeMaths.cs new file mode 100644 index 0000000..3a7c238 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/MaClasseDeMaths.cs @@ -0,0 +1,56 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MaClasseDeMath.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace Namespace2 +{ + /// + /// une classe qui réalise quelques opérations mathématiques + /// + public static class MaClasseDeMaths + { + /// + /// méthode static calculant a^b + /// Cette méthode n'est pas de type "Modifieur" car elle n'a pas la même signature que le délégué + /// + /// l'entier a élévé à la puissance b + /// l'exposant + /// a^b + public static int Power(int a, int b) + { + return (int)Math.Pow(a, b); + } + + /// + /// méthode calculant le carré d'un entier + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué + /// + /// entier élevé au carré + /// a^2 + public static int Carré(int a) + { + return a * a; + } + + /// + /// méthode calculant le cube d'un entier + /// Cette méthode est du type "Modifieur" car sa signature est la même que celle du délégué + /// + /// entier élevé au cube + /// a^3 + public static int Cube(int a) + { + return a * a * a; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/Program.cs b/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/Program.cs new file mode 100644 index 0000000..315dd87 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/Program.cs @@ -0,0 +1,74 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; + +using Namespace2; + +namespace Namespace1 +{ + class Program + { + /// + /// on définit le délégué ici avec la visibilité qui nous intéresse (ici j'ai choisi internal) + /// + /// un entier + /// un autre entier dépendant du paramètre et de l'exécution de la fonction de type Modifieur + internal delegate int Modifieur(int x); + + /// + /// instance du délégué de type délégué Modifieur déclaré au-dessus + /// + Modifieur MonModifieur; + + public void Modifie(int[] tab) + { + for (int i = 0; i < tab.Length; i++) + { + tab[i] = MonModifieur(tab[i]); + } + } + + public Program(Modifieur modifieur) + { + MonModifieur = modifieur; + } + + static void Main(string[] args) + { + int[] tableau = { 1, 2, 3, 4, 5 }; + Program p = new Program(MaClasseDeMaths.Carré); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + p = new Program(MaClasseDeMaths.Cube); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + p = new Program(new Droite(2, 3).Image); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + } + } + +} diff --git a/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/ex_028_007_delegate_versus_Strategy.csproj b/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/ex_028_007_delegate_versus_Strategy.csproj new file mode 100644 index 0000000..18cd0d5 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_007_delegate_versus_Strategy/ex_028_007_delegate_versus_Strategy.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_007_delegate_versus_Strategy + Exe + ex_028_007_delegate_versus_Strategy + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/AffichePourcentage.cs b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/AffichePourcentage.cs new file mode 100644 index 0000000..1b865ca --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/AffichePourcentage.cs @@ -0,0 +1,26 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AffichePourcentage.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; + +namespace ex_028_008_multicast_et_interfaces +{ + class AffichePourcentage : IProgression + { + public int Progression + { + set + { + WriteLine($"{value}%..."); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ClasseQuiFaitDuGrosTravail.cs b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ClasseQuiFaitDuGrosTravail.cs new file mode 100644 index 0000000..c6554c2 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ClasseQuiFaitDuGrosTravail.cs @@ -0,0 +1,47 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : ClasseQuiFaitDuGrosTravail.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_028_008_multicast_et_interfaces +{ + public class ClasseQuiFaitDuGrosTravail + { + List mProgressions = new List(); + + public void Attacher(IProgression prog) + { + mProgressions.Add(prog); + } + + public void Détacher(IProgression prog) + { + mProgressions.Remove(prog); + } + + void Notifier(int pourcentage) + { + foreach (IProgression prog in mProgressions) + { + prog.Progression = pourcentage; + } + } + + public void GrosTravail() + { + for (int i = 0; i <= 100; i++) + { + Notifier(i); + System.Threading.Thread.Sleep(50); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ClearProgression.cs b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ClearProgression.cs new file mode 100644 index 0000000..05f5020 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ClearProgression.cs @@ -0,0 +1,23 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : ClearProgression.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_028_008_multicast_et_interfaces +{ + class ClearProgression : IProgression + { + public int Progression + { + set { Console.Clear(); } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/IProgression.cs b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/IProgression.cs new file mode 100644 index 0000000..080bfb4 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/IProgression.cs @@ -0,0 +1,21 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : IProgression.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_008_multicast_et_interfaces +{ + public interface IProgression + { + int Progression // void SetProgression(int value) + { + set; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/Program.cs b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/Program.cs new file mode 100644 index 0000000..880fcf1 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/Program.cs @@ -0,0 +1,62 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Text; +using static System.Console; + +namespace ex_028_008_multicast_et_interfaces +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + WriteLine("Lancement du gros travail"); + ClasseQuiFaitDuGrosTravail cqfdgt = new ClasseQuiFaitDuGrosTravail(); + cqfdgt.GrosTravail(); + + + WriteLine(); + WriteLine("On attache une progression de type AffichePourcentage"); + WriteLine("Lancement du gros travail"); + IProgression p1 = new AffichePourcentage(); + cqfdgt.Attacher(p1); + cqfdgt.GrosTravail(); + + WriteLine(); + WriteLine("On attache une progression de type ProgressBar"); + WriteLine("Lancement du gros travail"); + IProgression p2 = new ProgressBar(); + cqfdgt.Attacher(p2); + cqfdgt.GrosTravail(); + + WriteLine(); + WriteLine("On détache une progression de type AffichePourcentage"); + WriteLine("Lancement du gros travail"); + cqfdgt.Détacher(p1); + cqfdgt.GrosTravail(); + + WriteLine(); + WriteLine("On détache une progression de type ProgressBar"); + cqfdgt.Détacher(p2); + + WriteLine("On attache une progression de type ClearProgression"); + WriteLine("On attache une progression de type ProgressBar"); + WriteLine("On attache une progression de type AffichePourcentage"); + WriteLine("Lancement du gros travail"); + cqfdgt.Attacher(new ClearProgression()); + cqfdgt.Attacher(new ProgressBar()); + cqfdgt.Attacher(new AffichePourcentage()); + cqfdgt.GrosTravail(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ProgressBar.cs b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ProgressBar.cs new file mode 100644 index 0000000..191e0da --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ProgressBar.cs @@ -0,0 +1,29 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : ProgressBar.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace ex_028_008_multicast_et_interfaces +{ + class ProgressBar : IProgression + { + static int MaxWidth = WindowWidth - 1; + + public int Progression + { + set + { + WriteLine(String.Empty.PadLeft(value * MaxWidth / 100, '*')); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ex_028_008_multicast_et_interfaces.csproj b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ex_028_008_multicast_et_interfaces.csproj new file mode 100644 index 0000000..339b6c0 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_008_multicast_et_interfaces/ex_028_008_multicast_et_interfaces.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_008_multicast_et_interfaces + Exe + ex_028_008_multicast_et_interfaces + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/GrosTravail.cs b/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/GrosTravail.cs new file mode 100644 index 0000000..24b2b69 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/GrosTravail.cs @@ -0,0 +1,64 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : GrosTravail.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace nsUtils +{ + /// + /// une classe qui fait un gros travail ... + /// + public class ClasseQuiFaitDuGrosTravail + { + /// + /// on définit le délégué ici dans le namespace nsUtils avec la visibilité qui nous intéresse (ici j'ai choisi public) + /// + /// un entier + public delegate void Progression(int pourcentage); + + /// + /// instance de délégué + /// + private Progression InstanceProgression; + + public void Initialiser(Progression prog) + { + InstanceProgression = prog; + } + + public void Attacher(Progression prog) + { + InstanceProgression += prog; + } + + public void Détacher(Progression prog) + { + InstanceProgression -= prog; + } + + /// + /// méthode statique qui appelle les méthodes pointées par la méthode p de type délégué Progression toutes les demi-secondes + /// + /// instance de délégué de type délégué "Progression" qui sera appelée à chaque dem-seconde + public void GrosTravail() + { + for (int i = 0; i <= 100; i++) + { + //exécution de l'instance de délégué + InstanceProgression?.Invoke(i); + //la ligne précédente est exactement équivalente à : + //if (InstanceProgression != null) + //{ + // InstanceProgression(i); + //} + System.Threading.Thread.Sleep(50); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/Program.cs b/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/Program.cs new file mode 100644 index 0000000..8b69e54 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/Program.cs @@ -0,0 +1,81 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; + +using nsUtils; +using System.Text; + +namespace ex_028_009_multicast_delegate +{ + class Program + { + /// + /// méthode de type délégué Progression (elle prend un entier et ne renvoie rien) qui affiche le pourcentage de progression + /// + /// pourcentage de progression + static void AffichePourcentage(int pourcentage) + { + WriteLine($"{pourcentage}% effectués..."); + } + + /// + /// méthode de type délégué Progression (elle prend un entier et ne renvoie rien) qui affiche des étoiles en fonction du pourcentage de progression + /// + /// pourcentage de progression + static void ProgressBar(int pourcentage) + { + WriteLine(String.Empty.PadLeft(pourcentage * (WindowWidth - 1) / 100, '*')); + } + + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + WriteLine("Lancement du gros travail"); + ClasseQuiFaitDuGrosTravail travail = new ClasseQuiFaitDuGrosTravail(); + travail.GrosTravail(); + WriteLine("fini"); + + //on prépare une instance de délégué du type délégué Progression pointant sur une seule méthode AffichePourcentage, + //et on appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("PREMIER APPEL"); + travail.Attacher(AffichePourcentage); + travail.GrosTravail(); + + //on ajoute une instance de délégué à notre "pointeur" : ProgressBar. + //L'instance de délégué p pointe maintenant sur deux méthodes qui sont exécutées l'une après l'autre à chaque appel. + //On appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("DEUXIEME APPEL"); + travail.Attacher(ProgressBar); + travail.GrosTravail(); + + //on retire une instance de délégué à notre "pointeur" : AffichePourcentagen. + //L'instance de délégué p pointe maintenant sur une seule méthode (ProgressBar). + //On appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("TROISIEME APPEL"); + travail.Détacher(AffichePourcentage); + travail.GrosTravail(); + + //on réinitialise p avec la méthode ClearConsole, puis on ajoute ProgressBar, puis AffichePourcentage + travail.Initialiser((i) => Clear()); + travail.Attacher(ProgressBar); + travail.Attacher(AffichePourcentage); + travail.GrosTravail(); + } + + static void ClearConsole(int pourcentage) + { + Clear(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/ex_028_009_multicast_delegate.csproj b/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/ex_028_009_multicast_delegate.csproj new file mode 100644 index 0000000..5f512e8 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_009_multicast_delegate/ex_028_009_multicast_delegate.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_009_multicast_delegate + Exe + ex_028_009_multicast_delegate + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/GrosTravail.cs b/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/GrosTravail.cs new file mode 100644 index 0000000..2f6d931 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/GrosTravail.cs @@ -0,0 +1,65 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : GrosTravail.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; + +namespace nsUtils +{ + /// + /// une classe qui fait un gros travail ... + /// + public class ClasseQuiFaitDuGrosTravail + { + /// + /// on définit le délégué ici dans le namespace nsUtils avec la visibilité qui nous intéresse (ici j'ai choisi public) + /// + /// un entier + /// la chaîne de caractères à afficher + public delegate string Progression(int pourcentage); + + /// + /// instance de délégué + /// + private Progression InstanceProgression; + + public void Initialiser(Progression prog) + { + InstanceProgression = prog; + } + + public void Attacher(Progression prog) + { + InstanceProgression += prog; + } + + public void Détacher(Progression prog) + { + InstanceProgression -= prog; + } + + /// + /// méthode statique qui appelle les méthodes pointées par la méthode p de type délégué Progression toutes les demi-secondes + /// + /// instance de délégué de type délégué "Progression" qui sera appelée à chaque dem-seconde + public void GrosTravail() + { + for (int i = 0; i <= 100; i++) + { + //exécution de l'instance de délégué + if (InstanceProgression != null) + { + WriteLine(InstanceProgression(i)); + } + System.Threading.Thread.Sleep(50); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/Program.cs b/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/Program.cs new file mode 100644 index 0000000..0cfd243 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/Program.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2014-04-27 +// Mise à jour : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; +using nsUtils; +using System.Text; + +namespace ex_028_010_multicast_delegate_return_value +{ + class Program + { + /// + /// méthode de type délégué Progression (elle prend un entier et ne renvoie rien) qui affiche le pourcentage de progression + /// + /// pourcentage de progression + static string AffichePourcentage(int pourcentage) + { + return $"{pourcentage}% effectués..."; + } + + /// + /// méthode de type délégué Progression (elle prend un entier et ne renvoie rien) qui affiche des étoiles en fonction du pourcentage de progression + /// + /// pourcentage de progression + static string ProgressBar(int pourcentage) + { + return String.Empty.PadLeft(pourcentage * (WindowWidth - 1) / 100, '*'); + } + + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + WriteLine("Lancement du gros travail"); + ClasseQuiFaitDuGrosTravail travail = new ClasseQuiFaitDuGrosTravail(); + travail.GrosTravail(); + WriteLine("fini"); + + //on prépare une instance de délégué du type délégué Progression pointant sur une seule méthode AffichePourcentage, + //et on appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("PREMIER APPEL"); + travail.Attacher(AffichePourcentage); + travail.GrosTravail(); + + //on ajoute une instance de délégué à notre "pointeur" : ProgressBar. + //L'instance de délégué p pointe maintenant sur deux méthodes qui sont exécutées l'une après l'autre à chaque appel. + //On appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("DEUXIEME APPEL"); + travail.Attacher(ProgressBar); + travail.GrosTravail(); + + //on retire une instance de délégué à notre "pointeur" : AffichePourcentagen. + //L'instance de délégué p pointe maintenant sur une seule méthode (ProgressBar). + //On appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("TROISIEME APPEL"); + travail.Détacher(AffichePourcentage); + travail.GrosTravail(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/ex_028_010_multicast_delegate_return_value.csproj b/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/ex_028_010_multicast_delegate_return_value.csproj new file mode 100644 index 0000000..456c2a2 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_010_multicast_delegate_return_value/ex_028_010_multicast_delegate_return_value.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_010_multicast_delegate_return_value + Exe + ex_028_010_multicast_delegate_return_value + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/Broadcaster.cs b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/Broadcaster.cs new file mode 100644 index 0000000..9e9b91d --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/Broadcaster.cs @@ -0,0 +1,38 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Broadcaster.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_028_011_Broadcaster_Subscriber +{ + class Broadcaster + { + List mSubscribers = new List(); + + public void Attach(ISubscriber subscriber) + { + mSubscribers.Add(subscriber); + } + + public void Detach(ISubscriber subscriber) + { + mSubscribers.Remove(subscriber); + } + + public void Notify() + { + foreach (ISubscriber subscriber in mSubscribers) + { + subscriber.Update(); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ConcreteSubscriber.cs b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ConcreteSubscriber.cs new file mode 100644 index 0000000..ccd5513 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ConcreteSubscriber.cs @@ -0,0 +1,37 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : ConcreteSubscriber.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; + +namespace ex_028_011_Broadcaster_Subscriber +{ + class ConcreteSubscriber : ISubscriber + { + public string Name + { + get; + private set; + } + + InfoSportBroadcaster mCaster; + + public ConcreteSubscriber(string name, InfoSportBroadcaster caster) + { + Name = name; + mCaster = caster; + } + + public void Update() + { + WriteLine($"{Name} a reçu l'info {mCaster.LastInfo} le {mCaster.LastDateTime.ToString("d")} à {mCaster.LastDateTime.ToString("t")}"); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ISubscriber.cs b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ISubscriber.cs new file mode 100644 index 0000000..024e13e --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ISubscriber.cs @@ -0,0 +1,18 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : ISubscriber.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace ex_028_011_Broadcaster_Subscriber +{ + public interface ISubscriber + { + void Update(); + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/InfoSportBroadcaster.cs b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/InfoSportBroadcaster.cs new file mode 100644 index 0000000..79a3420 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/InfoSportBroadcaster.cs @@ -0,0 +1,57 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : InfoSportBroadcaster.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_028_011_Broadcaster_Subscriber +{ + class InfoSportBroadcaster : Broadcaster + { + public string LastInfo + { + get + { + return mLastInfo; + } + private set + { + if (value != mLastInfo) + { + mLastInfo = value; + Notify(); + } + } + } + string mLastInfo; + + public DateTime LastDateTime + { + get + { + return mLastDateTime; + } + private set + { + if (value != mLastDateTime) + { + mLastDateTime = value; + } + } + } + DateTime mLastDateTime; + + public void AddInfo(string info) + { + LastDateTime = DateTime.Now; + LastInfo = info; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/Program.cs b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/Program.cs new file mode 100644 index 0000000..bb09052 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/Program.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Text; +using static System.Console; + +namespace ex_028_011_Broadcaster_Subscriber +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + InfoSportBroadcaster caster = new InfoSportBroadcaster(); + + ConcreteSubscriber arthur = new ConcreteSubscriber("Arthur", caster); + ConcreteSubscriber richard = new ConcreteSubscriber("Richard", caster); + + caster.Attach(arthur); + caster.AddInfo("L'ASM bat le Stade Français 28 à 25"); + System.Threading.Thread.Sleep(2000); + + caster.Attach(richard); + caster.AddInfo("Grenoble domine le Racing-Metro 27 à 13"); + System.Threading.Thread.Sleep(2000); + + caster.Detach(arthur); + caster.AddInfo("La Nouvelle-Zélande gagne le Four Nations en battant l'Argentine 54 à 15"); + System.Threading.Thread.Sleep(2000); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ex_028_011_Broadcaster_Subscriber.csproj b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ex_028_011_Broadcaster_Subscriber.csproj new file mode 100644 index 0000000..8a710ca --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_011_Broadcaster_Subscriber/ex_028_011_Broadcaster_Subscriber.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_011_Broadcaster_Subscriber + Exe + ex_028_011_Broadcaster_Subscriber + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Broadcaster.cs b/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Broadcaster.cs new file mode 100644 index 0000000..784a801 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Broadcaster.cs @@ -0,0 +1,77 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Broadcaster.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace Broadcaster_Subscriber +{ + /// + /// classe possédant un type délégué Information et une instance de ce délégué Informer + /// Elle diffuse des informations aux abonnés + /// + class Broadcaster + { + /// + /// type délégué (ne rend rien et prend en paramètres deux chaînes de caractères + /// + public delegate void Information(string info, DateTime date); + + /// + /// instance du délégué Information + /// + public Information Informer; + + public string Name + { + get; + private set; + } + + /// + /// information à diffuser (si celle-ci a été modifiée) + /// + public string Info + { + get { return mInfo; } + set + { + //si l'information n'est pas modifiée, on ne fait rien + if (mInfo == value) + { + return; + } + //sinon, on vérifie que l'instance de délégué n'est pas nulle (le pointeur pointe sur au moins une fonction) + //si elle n'est pas nulle, on exécute toutes les méthodes pointées + Informer?.Invoke(value, DateTime.Now); + + //la ligne précédente est exactement équivalente à : + //if (Informer != null) + //{ + // Informer(value, DateTime.Now); + //} + + mInfo = value; + } + } + string mInfo; + + /// + /// constructeur + /// + /// information de départ + public Broadcaster(string name) + { + Name = name; + } + + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Program.cs b/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Program.cs new file mode 100644 index 0000000..dca6370 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Program.cs @@ -0,0 +1,52 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Text; +using static System.Console; + +namespace Broadcaster_Subscriber +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + //création d'un diffuseur + Broadcaster info_sport = new Broadcaster("Info Sport"); + info_sport.Info = "Toulouse s'impose face à Toulon 32 à 9"; + + //deux instances d'Subscriber s'abonnent à l'instance de délégué info_sport.Informer + Subscriber arthur = new Subscriber("Arthur"); + arthur.Abonnement(info_sport); + info_sport.Info = "Grenoble domine le Racing-Metro 27 à 13"; + + Subscriber richard = new Subscriber("Richard"); + richard.Abonnement(info_sport); + + //une nouvelle info tombe, l'appel du setter de la propriété Broadcaster.Info va exécuter les méthodes pointées par l'instance + // de délégué info_sport.Informer, soit arthur.RecevoirInfo et richard.RecevoirInfo + info_sport.Info = "L'ASM bat le Stade Français 28 à 25"; + //Informer("L'ASM bat le Stade Français 28 à 25", DateTime.Now); + // <=> arthur.RecevoirInfo("L'ASM bat le Stade Français 28 à 25", DateTime.Now); + // richard.RecevoirInfo("L'ASM bat le Stade Français 28 à 25", DateTime.Now); + WriteLine(); + + //arthur désabonne richard et s'abonne tout seul + arthur.DésabonnerToutLeMondeSaufMoi(info_sport); + //un nouvelle info tombe, arthur reçoit l'info mais pas richard + info_sport.Info = "La Nouvelle-Zélande gagne le Four Nations en battant l'Argentine 54 à 15"; + + //c'est un peu nul quand même, qu'un abonné ait l'autorisation de désabonner les autres... + // A SUIVRE dans ex_029_001_event_Broadcaster_Subscriber + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Subscriber.cs b/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Subscriber.cs new file mode 100644 index 0000000..32475b5 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/Subscriber.cs @@ -0,0 +1,87 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Subscriber.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace Broadcaster_Subscriber +{ + /// + /// classe dont les instances vont s'abonner au type délégué Informer de la classe Broadcaster + /// + class Subscriber + { + /// + /// nom de l'abonné + /// + public string Name + { + get; + private set; + } + + /// + /// méthode du type délégué Broadcaster.Information + /// + public void RecevoirInfo(string info, DateTime date) + { + WriteLine($"{Name} a reçu l'info {info} le {date.ToString("d")} à {date.ToString("t")}"); + } + + /// + /// constructeur + /// + /// nom de l'abonné + public Subscriber(string nom) + { + Name = nom; + } + + /// + /// méthode permettant à l'instance d'Subscriber de s'abonner à l'instance de délégué Informer d'un Broadcaster + /// + /// le diffuseur + public void Abonnement(Broadcaster dif) + { + #region affichage console + ForegroundColor = ConsoleColor.DarkGray; + WriteLine($"{Name} vient de s'abonner à {dif.Name}"); + ForegroundColor = ConsoleColor.White; + #endregion + dif.Informer += RecevoirInfo; + } + + public void Désabonnement(Broadcaster dif) + { + #region affichage console + ForegroundColor = ConsoleColor.DarkGray; + WriteLine($"{Name} vient de se désabonner de {dif.Name}"); + ForegroundColor = ConsoleColor.White; + #endregion + dif.Informer -= RecevoirInfo; + } + + /// + /// méthode qui désabonne tous les autres abonnés à l'instance de délégué Broadcaster.Informer et qui ne garde que l'instance this + /// + /// le diffuseur + public void DésabonnerToutLeMondeSaufMoi(Broadcaster dif) + { + #region affichage console + ForegroundColor = ConsoleColor.DarkGray; + WriteLine($"{Name} vient de désabonner tout le monde sauf lui de {dif.Name}"); + ForegroundColor = ConsoleColor.White; + #endregion + dif.Informer = RecevoirInfo; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/ex_028_012_delegate_Broadcaster_Subscriber.csproj b/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/ex_028_012_delegate_Broadcaster_Subscriber.csproj new file mode 100644 index 0000000..fc6cd6e --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_012_delegate_Broadcaster_Subscriber/ex_028_012_delegate_Broadcaster_Subscriber.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_012_delegate_Broadcaster_Subscriber + Exe + ex_028_012_delegate_Broadcaster_Subscriber + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_013_Predicate/Program.cs b/p06_MoreAdvancedCSharp/ex_028_013_Predicate/Program.cs new file mode 100644 index 0000000..26dfa1f --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_013_Predicate/Program.cs @@ -0,0 +1,120 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-08 +// +// ======================================================================== + +using System; +using static System.Console; +using System.Linq; + +namespace ex_028_013_Predicate +{ + /// + /// .NET contient déjà un certain nombre de types délégués dans l'espace de noms System. + /// Parmi eux, on peut distinguer notamment la famille des Predicate, des Func et des Action. + /// Cet exemple présente le délégué Predicate. + /// + /// Le délégué Predicate prend un objet générique en paramètre et rend un booléen (true ou false). + /// N'importe quelle instance d'un Predicate est donc une méthode prenant un T en paramètre et rendant un bool. + /// + class Program + { + /// + /// Cette méthode vérifie si un nombre entier vérifie une condition + /// + /// + /// la condition à vérifier + /// + static bool CheckIfValid(int i, Predicate predicat) + { + return predicat(i); + } + + /// + /// Cette méthode vérifie si tous les nombres entiers du tableu tab vérifient une condition + /// + /// + /// la condition à vérifier + /// + static bool CheckIfValid(int[] tab, Predicate predicat) + { + bool result = true; + foreach (int i in tab) + { + result &= predicat(i); + } + return result; + } + + /// + /// Cette méthode prend un entier et rend un bool, + /// c'est donc une instance de Predicate + /// + /// + /// + static bool IsPair(int i) + { + return i % 2 == 0; + } + + /// + /// Cette méthode prend un entier et rend un bool, + /// c'est donc une instance de Predicate + /// + /// + /// + static bool IsHigherThan5(int i) + { + return i > 5; + } + + static void Main(string[] args) + { + WriteLine("CheckIfValid(4, IsPair) : "); + WriteLine(CheckIfValid(4, IsPair)); + WriteLine("CheckIfValid(7, IsPair) : "); + WriteLine(CheckIfValid(7, IsPair)); + + WriteLine("CheckIfValid(4, IsHigherThan5) : "); + WriteLine(CheckIfValid(4, IsHigherThan5)); + WriteLine("CheckIfValid(7, IsHigherThan5) : "); + WriteLine(CheckIfValid(7, IsHigherThan5)); + + WriteLine("CheckIfValid(new int[]{ 2, 4, 6, 8, 10}, IsPair) : "); + WriteLine(CheckIfValid(new int[] { 2, 4, 6, 8, 10 }, IsPair)); + WriteLine("CheckIfValid(new int[]{ 2, 4, 7, 8, 10}, IsPair) : "); + WriteLine(CheckIfValid(new int[] { 2, 4, 7, 8, 10 }, IsPair)); + + WriteLine("CheckIfValid(new int[] { 2, 4, 6, 8, 10 }, IsHigherThan5) : "); + WriteLine(CheckIfValid(new int[] { 2, 4, 6, 8, 10 }, IsHigherThan5)); + WriteLine("CheckIfValid(new int[] { 7, 8, 10 }, IsHigherThan5) : "); + WriteLine(CheckIfValid(new int[] { 7, 8, 10 }, IsHigherThan5)); + + //les Predicate se marient très bien avec les expressions lambda (cf. chap 30) + //qui permettent d'éviter de définir les méthodes + WriteLine("CheckIfValid(4, i => i%2==0) : "); + WriteLine(CheckIfValid(4, i => i % 2 == 0)); + WriteLine("CheckIfValid(7, i => i>5) : "); + WriteLine(CheckIfValid(7, i => i > 5)); + + //elles se marient également parfaitement avec LINQ (cf. chap31) + //Where par exemple prend un paramètre de type Predicate + //Voici un exemple avec une projection de Predicate et une aggregation qui déchire + WriteLine("CheckIfAllConditionsAreValid(2, i => i % 2 == 0, i => i > 5) : "); + WriteLine(CheckIfAllConditionsAreValid(2, i => i % 2 == 0, i => i > 5)); + WriteLine("CheckIfAllConditionsAreValid(6, i => i % 2 == 0, i => i > 5) : "); + WriteLine(CheckIfAllConditionsAreValid(6, i => i % 2 == 0, i => i > 5)); + } + + static bool CheckIfAllConditionsAreValid(int i, params Predicate[] predicats) + { + return predicats.Select(p => p(i)).Aggregate(true, (result, b) => result &= b); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_013_Predicate/ex_028_013_Predicate.csproj b/p06_MoreAdvancedCSharp/ex_028_013_Predicate/ex_028_013_Predicate.csproj new file mode 100644 index 0000000..b1a24de --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_013_Predicate/ex_028_013_Predicate.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_013_Predicate + Exe + ex_028_013_Predicate + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_014_Func/Droite.cs b/p06_MoreAdvancedCSharp/ex_028_014_Func/Droite.cs new file mode 100644 index 0000000..ce455ea --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_014_Func/Droite.cs @@ -0,0 +1,51 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Droite.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-08 +// +// ======================================================================== + +namespace Namespace2 +{ + /// + /// classe représentant une droite + /// + public class Droite + { + /// + /// valeur du point d'abscisse nul de la droite + /// + int mOffset; + + /// + /// coefficient directeur de la droite + /// + int mPente; + + /// + /// constructeur de la droite + /// + /// valeur du point d'abscisse nul + /// coefficient directeur de la droite + public Droite(int offset, int pente) + { + mOffset = offset; + mPente = pente; + } + + /// + /// calcul l'ordonnée d'un point de la droite à partir de son abscisse + /// Cette méthode est du type Func car sa signature est la même que celle du délégué. + /// + /// abscisse du point + /// ordonnée du point sur la droite + public int Image(int a) + { + return mOffset + mPente * a; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_014_Func/MaClasseDeMaths.cs b/p06_MoreAdvancedCSharp/ex_028_014_Func/MaClasseDeMaths.cs new file mode 100644 index 0000000..212f649 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_014_Func/MaClasseDeMaths.cs @@ -0,0 +1,55 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : MaClasseDeMaths.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-08 +// +// ======================================================================== + +using System; + +namespace Namespace2 +{ + /// + /// une classe qui réalise quelques opérations mathématiques + /// + public class MaClasseDeMaths + { + /// + /// méthode static calculant a^b + /// Cette méthode n'est pas de type Func car elle n'a pas la même signature que le délégué + /// + /// l'entier a élévé à la puissance b + /// l'exposant + /// a^b + public static int Power(int a, int b) + { + return (int)Math.Pow(a, b); + } + + /// + /// méthode calculant le carré d'un entier + /// Cette méthode est du type Func car sa signature est la même que celle du délégué + /// + /// entier élevé au carré + /// a^2 + public static int Carré(int a) + { + return a * a; + } + + /// + /// méthode calculant le cube d'un entier + /// Cette méthode est du type Func car sa signature est la même que celle du délégué + /// + /// entier élevé au cube + /// a^3 + public static int Cube(int a) + { + return a * a * a; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_014_Func/Program.cs b/p06_MoreAdvancedCSharp/ex_028_014_Func/Program.cs new file mode 100644 index 0000000..cf16cdc --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_014_Func/Program.cs @@ -0,0 +1,85 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-08 +// +// ======================================================================== + +using Namespace2; +using System; +using static System.Console; + +namespace ex_028_014_Func +{ + /// + /// .NET contient déjà un certain nombre de types délégués dans l'espace de noms System. + /// Parmi eux, on peut distinguer notamment la famille des Predicate, des Func et des Action. + /// Cet exemple présente le délégué Func. + /// + /// Le délégué Func est multi-générique et a la forme suivante : + /// delegate TResult Func(T1 arg1, T2 arg2); + /// Mais il y en a de nombreux dans le framework : + /// Func + /// Func + /// Func + /// Func + /// Func + /// Func + /// Func + /// + /// N'importe quelle instance d'un Func est donc une méthode prenant en paramètres + /// un T1, un T2, un T3, ... un Ti et rendant un TResult. + /// + /// Ils permettent de coder très rapidement une Strategy par exemple. + /// L'exemple suivant reprend le 028_007 en utilisant le délégué Func + /// + class Program + { + Func MonModifieur; + + public void Modifie(int[] tab) + { + for (int i = 0; i < tab.Length; i++) + { + tab[i] = MonModifieur(tab[i]); + } + } + + public Program(Func modifieur) + { + MonModifieur = modifieur; + } + + static void Main(string[] args) + { + int[] tableau = { 1, 2, 3, 4, 5 }; + Program p = new Program(MaClasseDeMaths.Carré); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + p = new Program(MaClasseDeMaths.Cube); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + + p = new Program(new Droite(2, 3).Image); + p.Modifie(tableau); + foreach (int i in tableau) + { + Write($"{i} "); + } + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_014_Func/ex_028_014_Func.csproj b/p06_MoreAdvancedCSharp/ex_028_014_Func/ex_028_014_Func.csproj new file mode 100644 index 0000000..06a817a --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_014_Func/ex_028_014_Func.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_014_Func + Exe + ex_028_014_Func + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_028_015_Action/GrosTravail.cs b/p06_MoreAdvancedCSharp/ex_028_015_Action/GrosTravail.cs new file mode 100644 index 0000000..03dd4d1 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_015_Action/GrosTravail.cs @@ -0,0 +1,60 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : GrosTravail.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-08 +// +// ======================================================================== + +using System; + +namespace nsUtils +{ + /// + /// une classe qui fait un gros travail ... + /// + public class ClasseQuiFaitDuGrosTravail + { + /// + /// instance de délégué + /// + private Action InstanceProgression; + + public void Initialiser(Action prog) + { + InstanceProgression = prog; + } + + public void Attacher(Action prog) + { + InstanceProgression += prog; + } + + public void Détacher(Action prog) + { + InstanceProgression -= prog; + } + + /// + /// méthode statique qui appelle les méthodes pointées par la méthode p de type délégué Progression toutes les demi-secondes + /// + /// instance de délégué de type délégué "Progression" qui sera appelée à chaque dem-seconde + public void GrosTravail() + { + for (int i = 0; i <= 100; i++) + { + //exécution de l'instance de délégué + InstanceProgression?.Invoke(i); + //la ligne précédente est exactement équivalente à : + //if (InstanceProgression != null) + //{ + // InstanceProgression(i); + //} + System.Threading.Thread.Sleep(50); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_015_Action/Program.cs b/p06_MoreAdvancedCSharp/ex_028_015_Action/Program.cs new file mode 100644 index 0000000..186d9cd --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_015_Action/Program.cs @@ -0,0 +1,99 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-08 +// +// ======================================================================== + +using System; +using static System.Console; +using nsUtils; + +namespace ex_028_015_Action +{ + /// + /// .NET contient déjà un certain nombre de types délégués dans l'espace de noms System. + /// Parmi eux, on peut distinguer notamment la famille des Predicate, des Func et des Action. + /// Cet exemple présente le délégué Action. + /// + /// Le délégué Action est multi-générique et a la forme suivante : + /// delegate TResult Action(T1 arg1, T2 arg2, T3 arg3); + /// Mais il y en a de nombreux dans le framework : + /// Action + /// Action + /// Action + /// Action + /// Action + /// Action + /// + /// N'importe quelle instance d'un Action est donc une méthode prenant en paramètres + /// un T1, un T2, un T3, ... un Ti et ne rendant rien (void). + /// + /// Comme Predicate et Func, ils sont très utilisés avec LINQ (chap 31) et profitent des méthodes anonymes (chap. 30) + /// + /// Cet exemple reprend l'exemple ex_028_009 en utilisant le délégué Action + /// + class Program + { + /// + /// méthode de type délégué Progression (elle prend un entier et ne renvoie rien) qui affiche le pourcentage de progression + /// + /// pourcentage de progression + static void AffichePourcentage(int pourcentage) + { + WriteLine($"{pourcentage}% effectués..."); + } + + /// + /// méthode de type délégué Progression (elle prend un entier et ne renvoie rien) qui affiche des étoiles en fonction du pourcentage de progression + /// + /// pourcentage de progression + static void ProgressBar(int pourcentage) + { + WriteLine(String.Empty.PadLeft(pourcentage * (WindowWidth - 1) / 100, '*')); + } + + static void Main(string[] args) + { + WriteLine("Lancement du gros travail"); + ClasseQuiFaitDuGrosTravail travail = new ClasseQuiFaitDuGrosTravail(); + travail.GrosTravail(); + WriteLine("fini"); + + //on prépare une instance de délégué du type délégué Progression pointant sur une seule méthode AffichePourcentage, + //et on appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("PREMIER APPEL"); + travail.Attacher(AffichePourcentage); + travail.GrosTravail(); + + //on ajoute une instance de délégué à notre "pointeur" : ProgressBar. + //L'instance de délégué p pointe maintenant sur deux méthodes qui sont exécutées l'une après l'autre à chaque appel. + //On appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("DEUXIEME APPEL"); + travail.Attacher(ProgressBar); + travail.GrosTravail(); + + //on retire une instance de délégué à notre "pointeur" : AffichePourcentagen. + //L'instance de délégué p pointe maintenant sur une seule méthode (ProgressBar). + //On appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("TROISIEME APPEL"); + travail.Détacher(AffichePourcentage); + travail.GrosTravail(); + + //on réinitialise p avec la méthode ClearConsole, puis on ajoute ProgressBar, puis AffichePourcentage + travail.Initialiser((i) => Clear()); + travail.Attacher(ProgressBar); + travail.Attacher(AffichePourcentage); + travail.GrosTravail(); + } + + static void ClearConsole(int pourcentage) + { + Clear(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_028_015_Action/ex_028_015_Action.csproj b/p06_MoreAdvancedCSharp/ex_028_015_Action/ex_028_015_Action.csproj new file mode 100644 index 0000000..b7f9612 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_028_015_Action/ex_028_015_Action.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_028_015_Action + Exe + ex_028_015_Action + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Broadcaster.cs b/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Broadcaster.cs new file mode 100644 index 0000000..dde5941 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Broadcaster.cs @@ -0,0 +1,76 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Broadcaster.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace Broadcaster_Subscriber +{ + /// + /// classe possédant un type délégué Information et une instance de ce délégué Informer + /// Elle diffuse des informations aux abonnés + /// + class Broadcaster + { + /// + /// type délégué (ne rend rien et prend en paramètres deux chaînes de caractères + /// + public delegate void Information(string info, DateTime date); + + /// + /// instance du délégué Information + /// + public event Information Informer; + + public string Name + { + get; + private set; + } + + /// + /// information à diffuser (si celle-ci a été modifiée) + /// + public string Info + { + get { return mInfo; } + set + { + //si l'information n'est pas modifiée, on ne fait rien + if (mInfo == value) + { + return; + } + //sinon, on vérifie que l'instance de délégué n'est pas nulle (le pointeur pointe sur au moins une fonction) + //si elle n'est pas nulle, on exécute toutes les méthodes pointées + Informer?.Invoke(value, DateTime.Now); + + //la ligne précédente est exactement équivalente à : + //if (Informer != null) + //{ + // Informer(value, DateTime.Now); + //} + + mInfo = value; + } + } + string mInfo; + + /// + /// constructeur + /// + /// information de départ + public Broadcaster(string name) + { + Name = name; + } + + } +} diff --git a/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Program.cs b/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Program.cs new file mode 100644 index 0000000..de991e1 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Program.cs @@ -0,0 +1,50 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Text; +using static System.Console; + +namespace Broadcaster_Subscriber +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + //création d'un diffuseur + Broadcaster info_sport = new Broadcaster("Info Sport"); + info_sport.Info = "Toulouse s'impose face à Toulon 32 à 9"; + + //deux instances d'Subscriber s'abonnent à l'instance de délégué info_sport.Informer + Subscriber arthur = new Subscriber("Arthur"); + arthur.Abonnement(info_sport); + info_sport.Info = "Grenoble domine le Racing-Metro 27 à 13"; + + Subscriber richard = new Subscriber("Richard"); + richard.Abonnement(info_sport); + + //une nouvelle info tombe, l'appel du setter de la propriété Broadcaster.Info va exécuter les méthodes pointées par l'instance + // de délégué info_sport.Informer, soit arthur.RecevoirInfo et richard.RecevoirInfo + info_sport.Info = "L'ASM bat le Stade Français 28 à 25"; + //Informer("L'ASM bat le Stade Français 28 à 25", DateTime.Now); + // <=> arthur.RecevoirInfo("L'ASM bat le Stade Français 28 à 25", DateTime.Now); + // richard.RecevoirInfo("L'ASM bat le Stade Français 28 à 25", DateTime.Now); + WriteLine(); + + //arthur désabonne richard et s'abonne tout seul + arthur.DésabonnerToutLeMondeSaufMoi(info_sport); + //un nouvelle info tombe, arthur reçoit l'info mais pas richard + info_sport.Info = "La Nouvelle-Zélande gagne le Four Nations en battant l'Argentine 54 à 15"; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Subscriber.cs b/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Subscriber.cs new file mode 100644 index 0000000..079fb5f --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/Subscriber.cs @@ -0,0 +1,90 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Subscriber.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; + +namespace Broadcaster_Subscriber +{ + /// + /// classe dont les instances vont s'abonner au type délégué Informer de la classe Broadcaster + /// + class Subscriber + { + /// + /// nom de l'abonné + /// + public string Name + { + get; + private set; + } + + /// + /// méthode du type délégué Broadcaster.Information + /// + public void RecevoirInfo(string info, DateTime date) + { + WriteLine($"{Name} a reçu l'info {info} le {date.ToString("d")} à {date.ToString("t")}"); + } + + /// + /// constructeur + /// + /// nom de l'abonné + public Subscriber(string nom) + { + Name = nom; + } + + /// + /// méthode permettant à l'instance d'Subscriber de s'abonner à l'instance de délégué Informer d'un Broadcaster + /// + /// le diffuseur + public void Abonnement(Broadcaster dif) + { + #region affichage console + ForegroundColor = ConsoleColor.DarkGray; + WriteLine($"{Name} vient de s'abonner à {dif.Name}"); + ForegroundColor = ConsoleColor.White; + #endregion + dif.Informer += RecevoirInfo; + } + + public void Désabonnement(Broadcaster dif) + { + #region affichage console + ForegroundColor = ConsoleColor.DarkGray; + WriteLine($"{Name} vient de se désabonner de {dif.Name}"); + ForegroundColor = ConsoleColor.White; + #endregion + dif.Informer -= RecevoirInfo; + } + + /// + /// méthode qui désabonne tous les autres abonnés à l'instance de délégué Broadcaster.Informer et qui ne garde que l'instance this + /// + /// le diffuseur + public void DésabonnerToutLeMondeSaufMoi(Broadcaster dif) + { + #region affichage console + ForegroundColor = ConsoleColor.DarkGray; + WriteLine($"{Name} vient de désabonner tout le monde sauf lui de {dif.Name}"); + ForegroundColor = ConsoleColor.White; + #endregion + //on ne peut plus utiliser l'operateur = car le mot clé event est utilisé + //devant l'instance de délégué + //il n'est donc plus possible, grâce au mot-clef event, de désabonner des méthodes provenant d'autres objets + //dif.Informer = RecevoirInfo; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/ex_029_001_event_Broadcaster_Subscriber.csproj b/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/ex_029_001_event_Broadcaster_Subscriber.csproj new file mode 100644 index 0000000..e54f2c6 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_001_event_Broadcaster_Subscriber/ex_029_001_event_Broadcaster_Subscriber.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_029_001_event_Broadcaster_Subscriber + Exe + ex_029_001_event_Broadcaster_Subscriber + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Broadcaster.cs b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Broadcaster.cs new file mode 100644 index 0000000..3f6b28d --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Broadcaster.cs @@ -0,0 +1,92 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Broadcaster.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace Broadcaster_Subscriber +{ + /// + /// classe générant l'événement + /// + public class Broadcaster + { + /// + /// type délégué de l'événement + /// Cette déclaration peut également être faite en dehors de la classe Broadcaster + /// + /// type des arguments d'événement (C# 2 et plus) + /// la source, c'est-à-dire l'objet qui générera l'événement + /// les arguments d'événement + /// Si vous avez plusieurs événements avec différentes implémentations de EventArgs, une seule déclaration de type délégué suffit ! + /// Grâce à la généricité, elle vaut pour tous les événements de type EventHandler avec TEventArgs qui s'adpate. + /// CETTE LIGNE EXISTE DEJA ET N'EST DONC PAS NECESSAIRE !!!! + //public delegate void EventHandler(object source, TEventArgs e) where TEventArgs : EventArgs; + + /// + /// déclaration de l'événement : + /// il est une instance du type délégué précédent, EventHandler, où TEventArgs vaut InfoChangedEventArgs. + /// Le mot clé event garantit qu'il s'agit d'un événement. + /// + public event EventHandler InfoChanged; + + /// + /// Cette méthode est celle qu'on appelle lorsqu'on veut lancer l'événement. + /// Elle vérifie d'abord que l'instance de délégué pointe sur au moins une méthode, si c'est le cas, elle génère l'événement. + /// Par convention, cette méthode commence par On... et continue avec le nom de l'événement ...InfoChanged. + /// On la choisit protected virtual pour qu'elle puisse être réimplémentée par les classes filles en général. Mais vous pouvez choisir un autre + /// degré d'accessibilité. + /// + /// arguments de cet événement + protected virtual void OnInfoChanged(InfoChangedEventArgs args) + { + InfoChanged?.Invoke(this, args); + //la ligne précédente est exactement équivalente à : + //if (InfoChanged != null) + //{ + // InfoChanged(this, args); + //} + } + + /// + /// propriété Info + /// + public string Info + { + get { return mInfo; } + set + { + if (mInfo == value) + { + return; + } + mInfo = value; + //génère l'événement avec des arguments construits à la volée + OnInfoChanged(new InfoChangedEventArgs(value, DateTime.Now)); + } + } + string mInfo; + + /// + /// nom du broadcaster + /// + public readonly string Name; + + /// + /// constructeur + /// + /// l'info + public Broadcaster(string name, string info) + { + Name = name; + Info = info; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/InfoChangedEventArgs.cs b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/InfoChangedEventArgs.cs new file mode 100644 index 0000000..3f04d01 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/InfoChangedEventArgs.cs @@ -0,0 +1,55 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : InfoChangedEventArgs.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace Broadcaster_Subscriber +{ + /// + /// classe propageant les arguments de l'événement + /// Dans le pattern standard, cette classe dérive de System.EventArgs + /// Par convention, son nom terminer en ...EventArgs. + /// Par convention, son nom débute par le nom de l'événement InfoChanged... + /// Elle ne contient que des propriétés en lecture seule ou des champs readonly public, et un constructeur pour les setter. + /// + public class InfoChangedEventArgs : System.EventArgs + { + /// + /// nouvelle info + /// + public string NewInfo + { + get; + private set; + } + + /// + /// date de parution de l'info + /// + public DateTime InfoDate + { + get; + private set; + } + + /// + /// constructeur + /// + /// nouvelle info + /// date de parution de l'info + public InfoChangedEventArgs(string new_info, DateTime info_date) + { + NewInfo = new_info; + InfoDate = info_date; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Program.cs b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Program.cs new file mode 100644 index 0000000..e7558ae --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Program.cs @@ -0,0 +1,37 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Text; +using static System.Console; + +namespace Broadcaster_Subscriber +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + //déclaration et affectation d'un Broadcaster + Broadcaster info_sport = new Broadcaster("info sport", "rien"); + + //déclaration et abonnement de deux Subscriber + Subscriber arthur = new Subscriber("Arthur"); + arthur.Subscribe(info_sport); + Subscriber richard = new Subscriber("Richard"); + richard.Subscribe(info_sport); + + //génération d'une nouvelle info + info_sport.Info = "Del Potro bat Federer en finale de l'US Open"; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Subscriber.cs b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Subscriber.cs new file mode 100644 index 0000000..4fa18b6 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/Subscriber.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Subscriber.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; +namespace Broadcaster_Subscriber +{ + /// + /// la classe dont les instances vont s'abonner à l'événement + /// + public class Subscriber + { + /// + /// nom du subscriber + /// + public readonly string Name; + + /// + /// méthode ayant la même signature que l'événement, elle peut donc s'abonner. + /// + /// celui qui génère l'événement + /// arguments de l'événement + public void ReceiveInfo(object sender, InfoChangedEventArgs args) + { + ForegroundColor = ConsoleColor.Red; + Write(Name); + ForegroundColor = ConsoleColor.White; + Write(" a reçu l'info : "); + ForegroundColor = ConsoleColor.DarkGreen; + Write(args.NewInfo); + ForegroundColor = ConsoleColor.White; + Write(" à "); + ForegroundColor = ConsoleColor.DarkGreen; + Write(args.InfoDate.ToString("t")); + ForegroundColor = ConsoleColor.White; + Write(" provenant de "); + ForegroundColor = ConsoleColor.Red; + WriteLine((sender as Broadcaster).Name); + ForegroundColor = ConsoleColor.White; + } + + /// + /// constructeur + /// + /// nom de l'abonné + public Subscriber(string name) + { + Name = name; + } + + /// + /// abonnement de cette instance de Subscriber à l'événement de Broadcaster + /// + /// le Broadcaster possédant l'événement auquel s'abonne ce Subscriber + public void Subscribe(Broadcaster br) + { + //abonnement, on peut utiliser += avec une méthode de cette instance de Subscriber + br.InfoChanged += ReceiveInfo; + } + } +} + diff --git a/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/ex_029_002_event_standard_pattern.csproj b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/ex_029_002_event_standard_pattern.csproj new file mode 100644 index 0000000..4879234 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_029_002_event_standard_pattern/ex_029_002_event_standard_pattern.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_029_002_event_standard_pattern + Exe + ex_029_002_event_standard_pattern + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_030_001_anonymousMethods/Program.cs b/p06_MoreAdvancedCSharp/ex_030_001_anonymousMethods/Program.cs new file mode 100644 index 0000000..d90b801 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_030_001_anonymousMethods/Program.cs @@ -0,0 +1,64 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Text; +using static System.Console; + +namespace ex_030_001_anonymousMethods +{ + class Program + { + /// + /// le délégué + /// + /// un entier + /// un autre entier dépendant du paramètre et de l'exécution de la fonction de type Modifieur + delegate int Modifieur(int x); + + delegate int Opération(int x, int y); + + /// + /// ici, on a une méthode "m" de type "Modifieur" (le délégué juste au-dessus) + /// et on l'affecte avec différentes "valeurs" (ici méthodes) possibles. + /// + /// + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + //on affecte une méthode anonyme à m + Modifieur m = delegate (int x) { return x * 2; }; + int resultat = m(3); + WriteLine($"m(3) = {resultat}"); + WriteLine($"m.Target == null ? {m.Target == null}"); + + //on affecte une autre méthode anonyme à m + m = delegate (int x) { return x * x; }; + resultat = m(3); + WriteLine($"m(3) = {resultat}"); + WriteLine($"m.Target == null ? {m.Target == null}"); + + //on affecte à m une méthode anonyme utilisant des variables locales + int offset = 1, pente = 2; + m = delegate (int x) { return offset + pente * x; }; + resultat = m(3); + WriteLine($"m(3) = {resultat}"); + WriteLine($"m.Target == null ? {m.Target == null}"); + WriteLine($"m.Target : {m.Target}"); + + Opération o = delegate (int x, int y) { return x * y; }; + WriteLine($"2x3 = {o(2, 3)}"); + + o = delegate (int x, int y) { return y - 2; }; + WriteLine($"3-2 = {o(2, 3)}"); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_030_001_anonymousMethods/ex_030_001_anonymousMethods.csproj b/p06_MoreAdvancedCSharp/ex_030_001_anonymousMethods/ex_030_001_anonymousMethods.csproj new file mode 100644 index 0000000..50b61db --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_030_001_anonymousMethods/ex_030_001_anonymousMethods.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_030_001_anonymousMethods + Exe + ex_030_001_anonymousMethods + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_030_002_lambdaExpressions/Program.cs b/p06_MoreAdvancedCSharp/ex_030_002_lambdaExpressions/Program.cs new file mode 100644 index 0000000..1fde4a2 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_030_002_lambdaExpressions/Program.cs @@ -0,0 +1,60 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; + +namespace ex_030_002_lambdaExpressions +{ + class Program + { + delegate int Modification(int i); + + delegate int Modification2(int i, int j); + + + static void Main(string[] args) + { + Modification carré = x => x * x; + WriteLine(carré(3)); + + //équivalent à : + //Modification carré = Carré + //WriteLine(carré(3)); + + Modification2 multi = (i, j) => i * j; + Modification2 somme = (i, j) => i + j; + WriteLine(multi(1, 2)); + WriteLine(somme(1, 2)); + + + + //on affecte une expression lambda à m + Modification m = i => i * 2; + int resultat = m(3); + WriteLine($"m(3) = {resultat}"); + WriteLine($"m.Target == null ? {m.Target == null}"); + + //on affecte une autre expression lambda à m + m = i => i * i; + resultat = m(3); + WriteLine($"m(3) = {resultat}"); + WriteLine($"m.Target == null ? {m.Target == null}"); + + //on affecte à m une autre expression lambda utilisant des variables locales à Program + int offset = 1, pente = 2; + m = i => offset + pente * i; + resultat = m(3); + WriteLine($"m(3) = {resultat}"); + WriteLine($"m.Target == null ? {m.Target == null}"); + WriteLine($"m.Target : {m.Target}"); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_030_002_lambdaExpressions/ex_030_002_lambdaExpressions.csproj b/p06_MoreAdvancedCSharp/ex_030_002_lambdaExpressions/ex_030_002_lambdaExpressions.csproj new file mode 100644 index 0000000..c265287 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_030_002_lambdaExpressions/ex_030_002_lambdaExpressions.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_030_002_lambdaExpressions + Exe + ex_030_002_lambdaExpressions + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/GrosTravail.cs b/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/GrosTravail.cs new file mode 100644 index 0000000..24b2b69 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/GrosTravail.cs @@ -0,0 +1,64 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : GrosTravail.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +namespace nsUtils +{ + /// + /// une classe qui fait un gros travail ... + /// + public class ClasseQuiFaitDuGrosTravail + { + /// + /// on définit le délégué ici dans le namespace nsUtils avec la visibilité qui nous intéresse (ici j'ai choisi public) + /// + /// un entier + public delegate void Progression(int pourcentage); + + /// + /// instance de délégué + /// + private Progression InstanceProgression; + + public void Initialiser(Progression prog) + { + InstanceProgression = prog; + } + + public void Attacher(Progression prog) + { + InstanceProgression += prog; + } + + public void Détacher(Progression prog) + { + InstanceProgression -= prog; + } + + /// + /// méthode statique qui appelle les méthodes pointées par la méthode p de type délégué Progression toutes les demi-secondes + /// + /// instance de délégué de type délégué "Progression" qui sera appelée à chaque dem-seconde + public void GrosTravail() + { + for (int i = 0; i <= 100; i++) + { + //exécution de l'instance de délégué + InstanceProgression?.Invoke(i); + //la ligne précédente est exactement équivalente à : + //if (InstanceProgression != null) + //{ + // InstanceProgression(i); + //} + System.Threading.Thread.Sleep(50); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/Program.cs b/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/Program.cs new file mode 100644 index 0000000..c405385 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/Program.cs @@ -0,0 +1,56 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; +using nsUtils; +using System.Text; + +namespace ex_030_003_lambdaExpressions +{ + class Program + { + //ex_04_009 avec des expressions lambda + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + ClasseQuiFaitDuGrosTravail travail = new ClasseQuiFaitDuGrosTravail(); + //travail.GrosTravail(); + WriteLine("fini"); + + //on prépare une instance de délégué du type délégué Progression pointant sur une seule expression lambda, + //et on appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("PREMIER APPEL"); + ClasseQuiFaitDuGrosTravail.Progression affiche = pourcentage => WriteLine($"{pourcentage}% effectués..."); + travail.Attacher(affiche); + //travail.GrosTravail(); + + //on ajoute une instance de délégué à notre "pointeur" : une autre expression lambda. + //L'instance de délégué p pointe maintenant sur deux méthodes qui sont exécutées l'une après l'autre à chaque appel. + //On appelle la méthode GrosTravail avec cette instance en paramètre. + WriteLine("DEUXIEME APPEL"); + travail.Attacher(pourcentage => WriteLine(String.Empty.PadLeft(pourcentage * (WindowWidth - 1) / 100, '*'))); + //travail.GrosTravail(); + + //on retire une instance de délégué à notre "pointeur", mais ce n'est plus possible avec les méthodes anonymes, même si on retape la même ! + WriteLine("TROISIEME APPEL"); + travail.Détacher(affiche); + //travail.GrosTravail(); + + //on réinitialise p avec une nouvelle expression lambda, puis on en ajoute 2 autres + travail.Initialiser(pourcentage => Clear()); + travail.Attacher(pourcentage => WriteLine(String.Empty.PadLeft(pourcentage * (WindowWidth - 1) / 100, '*'))); + travail.Attacher(pourcentage => WriteLine($"{pourcentage}% effectués...")); + travail.GrosTravail(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/ex_030_003_lambdaExpressions.csproj b/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/ex_030_003_lambdaExpressions.csproj new file mode 100644 index 0000000..378a411 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_030_003_lambdaExpressions/ex_030_003_lambdaExpressions.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_030_003_lambdaExpressions + Exe + ex_030_003_lambdaExpressions + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/Nounours.cs new file mode 100644 index 0000000..c33d976 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/Nounours.cs @@ -0,0 +1,81 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_031_001_decouverteDeLINQ +{ + class Nounours + { + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public int Taille + { + get; + private set; + } + + public bool IsGentil + { + get; + private set; + } + + public bool IsToutDoux + { + get; + private set; + } + + public int Odeur + { + get; + private set; + } + + public Nounours(string nom, DateTime naissance, int nbPoils, int taille, bool isGentil, bool isToutDoux, int odeur) + { + Nom = nom; + Naissance = naissance; + NbPoils = nbPoils; + Taille = taille; + IsGentil = isGentil; + IsToutDoux = isToutDoux; + Odeur = odeur; + } + + public static Nounours[] TousMesNounours = { new Nounours("Sinsin le singe", new DateTime(1987, 1, 1), 54, 35, true, false, 10), + new Nounours("Lapin le lapin", new DateTime(1997, 1, 1), 325, 85, true, true, 1), + new Nounours("Chucky la poupée de sang", new DateTime(1988, 1, 1), 13, 30, false, false, 5), + new Nounours("Popeye le marin", new DateTime(1929, 1, 1), 0, 165, true, false, 0), + new Nounours("Gizmo le mogwai", new DateTime(1984, 1, 1), 3678, 25, true, true, 2), + new Nounours("LaCrête le gremlin", new DateTime(1984, 1, 1), 5, 35, false, false, 10), + new Nounours("Caillou", new DateTime(1997, 1, 1), 0, 95, false, false, 4), + new Nounours("Olivier", new DateTime(1993, 1, 1), 4, 154, true, true, 0), + new Nounours("José l'ours polaire", DateTime.Now, 8, 212, false, true, 7) }; + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/Program.cs b/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/Program.cs new file mode 100644 index 0000000..67606e4 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/Program.cs @@ -0,0 +1,276 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using static System.Console; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ex_031_001_decouverteDeLINQ +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + AfficheNounours(); + WriteLine(string.Empty.PadLeft(WindowWidth - 1, '*')); + AfficheNounours2(); + WriteLine(string.Empty.PadLeft(WindowWidth - 1, '*')); + AfficheNounours3(); + WriteLine(string.Empty.PadLeft(WindowWidth - 1, '*')); + AfficheNounours4(); + WriteLine(string.Empty.PadLeft(WindowWidth - 1, '*')); + AfficheNounours5(nounours => nounours.NbPoils > 0); + WriteLine(string.Empty.PadLeft(WindowWidth - 1, '*')); + AfficheNounours6(nounours => nounours.NbPoils > 0); + WriteLine(string.Empty.PadLeft(WindowWidth - 1, '*')); + AfficheNounours7(nounours => nounours.NbPoils > 0); + WriteLine(string.Empty.PadLeft(WindowWidth - 1, '*')); + AfficheNounours8(nounours => nounours.NbPoils > 0); + } + + /// + /// un exemple classique de traitement de collection + /// + static void AfficheNounours() + { + List nounours = new List(); + foreach (Nounours n in Nounours.TousMesNounours) + { + if (n.NbPoils > 0) + { + nounours.Add(n.Nom); + } + } + + // plus loin ou ailleurs... + foreach (string s in nounours) + { + WriteLine(s); + } + } + + class NounoursData + { + public string Nom + { + get; + set; + } + + public int AnnéeNaissance + { + get; + set; + } + + public int NbPoils + { + get; + set; + } + + public override string ToString() + { + return $"Nom = {Nom}\tAnnéeNaissance = {AnnéeNaissance}\tNbPoils = {NbPoils}"; + } + } + + /// + /// un exemple classique de traitement de collection + /// + static void AfficheNounours2() + { + List nounoursDatas = new List(); + foreach (Nounours nounours in Nounours.TousMesNounours) + { + if (nounours.NbPoils > 0) + { + NounoursData data = new NounoursData(); + data.Nom = nounours.Nom; + data.AnnéeNaissance = nounours.Naissance.Year; + data.NbPoils = nounours.NbPoils; + nounoursDatas.Add(data); + } + } + + foreach (NounoursData data in nounoursDatas) + { + WriteLine(data); + } + } + + /// + /// utilisation de var (variable implicitement typée) + /// + static void AfficheNounours3() + { + var nounoursDatas = new List(); + foreach (var nounours in Nounours.TousMesNounours) + { + if (nounours.NbPoils > 0) + { + var data = new NounoursData(); + data.Nom = nounours.Nom; + data.AnnéeNaissance = nounours.Naissance.Year; + data.NbPoils = nounours.NbPoils; + nounoursDatas.Add(data); + } + } + + foreach (var data in nounoursDatas) + { + WriteLine(data); + } + } + + /// + /// utilisation des initializers + /// + static void AfficheNounours4() + { + var nounoursDatas = new List(); + foreach (var nounours in Nounours.TousMesNounours) + { + if (nounours.NbPoils > 0) + { + nounoursDatas.Add(new NounoursData + { + Nom = nounours.Nom, + AnnéeNaissance = nounours.Naissance.Year, + NbPoils = nounours.NbPoils + }); + } + } + + foreach (var data in nounoursDatas) + { + WriteLine(data); + } + } + + /// + /// expression lambda + /// + /// + static void AfficheNounours5(Predicate sélection) + { + var nounoursDatas = new List(); + foreach (var nounours in Nounours.TousMesNounours) + { + if (sélection(nounours)) + { + nounoursDatas.Add(new NounoursData + { + Nom = nounours.Nom, + AnnéeNaissance = nounours.Naissance.Year, + NbPoils = nounours.NbPoils + }); + } + } + + foreach (var data in nounoursDatas) + { + WriteLine(data); + } + } + + /// + /// méthode d'extensions + /// + /// + static void AfficheNounours6(Predicate sélection) + { + var nounoursDatas = new List(); + foreach (var nounours in Nounours.TousMesNounours) + { + if (sélection(nounours)) + { + nounoursDatas.Add(new NounoursData + { + Nom = nounours.Nom, + AnnéeNaissance = nounours.Naissance.Year, + NbPoils = nounours.NbPoils + }); + } + } + + int nbPoils = nounoursDatas.OrderByDescending(nounours => nounours.AnnéeNaissance) + .Take(2) + .Sum(nounours => nounours.NbPoils); + + foreach (var data in nounoursDatas) + { + WriteLine(data); + } + WriteLine($"Les deux nounours les plus jeunes possèdent à eux deux {nbPoils} poils"); + } + + /// + /// utilisation d'un type anonyme + /// + /// + static void AfficheNounours7(Predicate sélection) + { + var nounoursDatas = new List(); + foreach (var nounours in Nounours.TousMesNounours) + { + if (sélection(nounours)) + { + nounoursDatas.Add(new + { + Nom = nounours.Nom, + AnnéeNaissance = nounours.Naissance.Year, + NbPoils = nounours.NbPoils + }); + } + } + + //int nbPoils = nounoursDatas.OrderByDescending(nounours => nounours.AnnéeNaissance) + // .Take(2) + // .Sum(nounours => nounours.NbPoils); + + foreach (var data in nounoursDatas) + { + WriteLine(data); + } + //WriteLine($"Les deux nounours les plus jeunes possèdent à eux deux {nbPoils} poils"); + } + + /// + /// LINQ dans toute sa puissance + /// + /// + static void AfficheNounours8(Predicate sélection) + { + var nounoursDatas = Nounours.TousMesNounours.Where(nounours => sélection(nounours)) + .Select(nounours => new + { + Nom = nounours.Nom, + AnnéeNaissance = nounours.Naissance.Year, + NbPoils = nounours.NbPoils + }); + + int nbPoils = nounoursDatas.OrderByDescending(nounours => nounours.AnnéeNaissance) + .Take(2) + .Sum(nounours => nounours.NbPoils); + + foreach (var data in nounoursDatas) + { + WriteLine(data); + } + WriteLine($"Les deux nounours les plus jeunes possèdent à eux deux {nbPoils} poils"); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/ex_031_001_decouverteDeLINQ.csproj b/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/ex_031_001_decouverteDeLINQ.csproj new file mode 100644 index 0000000..da3bff0 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_001_decouverteDeLINQ/ex_031_001_decouverteDeLINQ.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_001_decouverteDeLINQ + Exe + ex_031_001_decouverteDeLINQ + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_002_extensionMethods/Program.cs b/p06_MoreAdvancedCSharp/ex_031_002_extensionMethods/Program.cs new file mode 100644 index 0000000..8b9ca42 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_002_extensionMethods/Program.cs @@ -0,0 +1,69 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; +using System.Text; + +namespace ex_031_002_extensionMethods +{ + //la classe doit être statique + public static class MyStringAdds + { + //il faut utiliser le this dans la signature + public static string Comment(this string s) + { + return $"/* {s} */"; + } + + public static string DeleteWhiteSpaces(this string s) + { + StringBuilder str = new StringBuilder(s); + str.Replace(" ", "-"); + return str.ToString(); + } + + public static int Inverse(this int i) + { + return -i; + } + + public static int CountNonWhiteSpacesCharacters(this string s, int index) + { + int nb = 0; + for (int i = index; i < s.Length; i++) + { + if (s[i] != ' ') + { + nb++; + } + } + return nb; + } + } + + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + string s = "Voici une phrase inintéressante"; + WriteLine(s); + WriteLine(s.Comment()); + WriteLine(s.DeleteWhiteSpaces()); + WriteLine(s.Comment().DeleteWhiteSpaces()); + WriteLine(s.DeleteWhiteSpaces().Comment()); + WriteLine(s.CountNonWhiteSpacesCharacters(0)); + WriteLine(s.CountNonWhiteSpacesCharacters(12)); + WriteLine(s.DeleteWhiteSpaces().CountNonWhiteSpacesCharacters(0).Inverse()); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_002_extensionMethods/ex_031_002_extensionMethods.csproj b/p06_MoreAdvancedCSharp/ex_031_002_extensionMethods/ex_031_002_extensionMethods.csproj new file mode 100644 index 0000000..3501bca --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_002_extensionMethods/ex_031_002_extensionMethods.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_002_extensionMethods + Exe + ex_031_002_extensionMethods + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_003_anonymousTypes/Program.cs b/p06_MoreAdvancedCSharp/ex_031_003_anonymousTypes/Program.cs new file mode 100644 index 0000000..9008972 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_003_anonymousTypes/Program.cs @@ -0,0 +1,71 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; +using System.Linq; +using System.Text; + +namespace ex_031_003_anonymousTypes +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + var nounours = new { Nom = "Boule de poils", Age = 5 }; + + //équivalent à : + + /* + * internal class TypeAnonymeGénéré + * { + * private string name; + * private int age; + * + * public TypeAnonymeGénéré (string name, int age) + * { + * this.name = name; + * this.age = age; + * } + * + * public string Nom + * { + * get + * { + * return name; + * } + * } + * + * public int Age + * { + * get + * { + * return age; + * } + * } + * + * //Equals, GetHashCode, ToString réécrites + * } + * ... + * var nounours = new TypeAnonymeGénéré("Boule de poils", 5); + * */ + + //un exemple où c'est bien pratique : + string[] bestioles = { "serpent", "chat", "éléphant", "chien", "étudiant", "souris", "singe", "bisounours", "hydralisk", "macaque", "cheval" }; + var result = bestioles.Select(bestiole => new { Nom = bestiole, Taille = bestiole.Length, Première_Lettre = bestiole[0] }); + foreach (var r in result) + { + WriteLine($"{r.Nom} ({r.Taille} lettres) /{r.Première_Lettre.ToString().ToUpper()}/"); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_003_anonymousTypes/ex_031_003_anonymousTypes.csproj b/p06_MoreAdvancedCSharp/ex_031_003_anonymousTypes/ex_031_003_anonymousTypes.csproj new file mode 100644 index 0000000..8fa1771 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_003_anonymousTypes/ex_031_003_anonymousTypes.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_003_anonymousTypes + Exe + ex_031_003_anonymousTypes + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_004_LINQ_intro/Program.cs b/p06_MoreAdvancedCSharp/ex_031_004_LINQ_intro/Program.cs new file mode 100644 index 0000000..2970765 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_004_LINQ_intro/Program.cs @@ -0,0 +1,132 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using static System.Console; + +namespace ex_031_004_LINQ_intro +{ + class Program + { + class Nounours + { + public Nounours(string nom, DateTime naissance) + { + Nom = nom; + Naissance = naissance; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + } + + static void Display(Nounours[] nounours) + { + WriteLine("début"); + foreach (Nounours n in nounours) + { + WriteLine($"{n.Nom}({n.Naissance})"); + } + WriteLine("fin"); + } + + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + Nounours[] nounours = { new Nounours("mouton", new DateTime(2009, 09, 16)), + new Nounours("ours", new DateTime(2009, 08, 15)), + new Nounours("chat", new DateTime(2009, 07, 14)), + new Nounours("chien", new DateTime(2009, 06, 13)), + new Nounours("lapin", new DateTime(2009, 05, 12)), + new Nounours("macaque", new DateTime(2009, 04, 11))}; + Display(nounours); + + //lambda queries + IEnumerable filteredNounours; + filteredNounours = nounours.Where(n => n.Nom.Length >= 5); + Display(filteredNounours.ToArray()); + + filteredNounours = nounours.Where(n => n.Naissance > new DateTime(2009, 07, 31)); + Display(filteredNounours.ToArray()); + //on peut chainer + filteredNounours = nounours.Where(n => n.Nom.Length >= 5) + .Where(n => n.Naissance > new DateTime(2009, 07, 31)); + Display(filteredNounours.ToArray()); + + // comprehension queries + filteredNounours = from n in nounours + where n.Nom.Length >= 5 + select n; + Display(filteredNounours.ToArray()); + + filteredNounours = from n in nounours + where n.Naissance > new DateTime(2009, 07, 31) + select n; + Display(filteredNounours.ToArray()); + + filteredNounours = from n in nounours + where n.Nom.Length >= 5 + where n.Naissance > new DateTime(2009, 07, 31) + select n; + Display(filteredNounours.ToArray()); + + //orderby + filteredNounours = nounours.Where(n => n.Nom.Length >= 5).OrderBy(n => n.Nom); + Display(filteredNounours.ToArray()); + + //Take + filteredNounours = nounours.Take(3).OrderBy(n => n.Nom); + Display(filteredNounours.ToArray()); + + //Skip + filteredNounours = nounours.Skip(3).OrderBy(n => n.Nom); + Display(filteredNounours.ToArray()); + + //Reverse + filteredNounours = nounours.OrderBy(n => n.Nom).Reverse(); + Display(filteredNounours.ToArray()); + + //First, Last, ElementAt + filteredNounours = nounours.OrderBy(n => n.Nom); + WriteLine($"1st {filteredNounours.First().Nom}\nlast {filteredNounours.Last().Nom}\n2nd {filteredNounours.ElementAt(1).Nom}"); + + //deferred execution + filteredNounours = nounours.Where(n => n.Nom.Contains("i")); + Display(filteredNounours.ToArray()); + Nounours[] tab_nounours = filteredNounours.ToArray(); + + nounours[0] = new Nounours("girafe", new DateTime(2007, 08, 09)); + + //filteredNounours = nounours.Where(n => n.Nom.Contains("i")); + Display(tab_nounours); + Display(filteredNounours.ToArray()); + + //subqueries + filteredNounours = nounours.Where(n => n.Nom.Length + == nounours.OrderBy(n2 => n2.Nom.Length) + .Select(n2 => n2.Nom.Length).First()); + Display(filteredNounours.ToArray()); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_004_LINQ_intro/ex_031_004_LINQ_intro.csproj b/p06_MoreAdvancedCSharp/ex_031_004_LINQ_intro/ex_031_004_LINQ_intro.csproj new file mode 100644 index 0000000..825c379 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_004_LINQ_intro/ex_031_004_LINQ_intro.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_036.0.6_LINQ_intro + Exe + ex_036.0.6_LINQ_intro + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/Nounours.cs new file mode 100644 index 0000000..4125cc6 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/Nounours.cs @@ -0,0 +1,36 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_031_005_LINQ_deferredExecution +{ + class Nounours + { + public Nounours(string nom, DateTime naissance) + { + Nom = nom; + Naissance = naissance; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/Program.cs b/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/Program.cs new file mode 100644 index 0000000..5b44f6c --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/Program.cs @@ -0,0 +1,62 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ex_031_005_LINQ_deferredExecution +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.Unicode; + + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16)), + new Nounours("ours", new DateTime(2009, 08, 15)), + new Nounours("chat", new DateTime(2009, 07, 14)), + new Nounours("chien", new DateTime(2009, 06, 13)), + new Nounours("lapin", new DateTime(2009, 05, 12)), + new Nounours("macaque", new DateTime(2009, 04, 11))}; + + //définition de la requête + //ATTENTION : ici, la requête est définie, mais n'est pas exécutée ! + var filteredNounours = nounours.Where(n => n.Nom.StartsWith("c")); + + //ici, nous avons besoin du résultat de la requête, donc elle est exécutée maintenant + //c'est l'exécution différée + WriteLine("1ère exécution de la requête"); + foreach (var n in filteredNounours) + { + WriteLine($"\t{n.Nom}"); + } + WriteLine(); + + //on ajoute un nouveau nounours + nounours.Add(new Nounours("canari", DateTime.Today)); + + //notez qu'ici, nous ne redéfinissons pas la requête, + //elle est juste exécutée à nouveau, mais comme la collection sur laquelle elle est construite a changé, + //alors le résultat de la requête également + //=> exécution différée + WriteLine("2ème exécution de la requête"); + foreach (var n in filteredNounours) + { + WriteLine($"\t{n.Nom}"); + } + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/ex_031_005_LINQ_deferredExecution.csproj b/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/ex_031_005_LINQ_deferredExecution.csproj new file mode 100644 index 0000000..09b51d1 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_005_LINQ_deferredExecution/ex_031_005_LINQ_deferredExecution.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_005_LINQ_deferredExecution + Exe + ex_031_005_LINQ_deferredExecution + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_005_LINQ_operators/Program.cs b/p06_MoreAdvancedCSharp/ex_031_005_LINQ_operators/Program.cs new file mode 100644 index 0000000..05e190f --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_005_LINQ_operators/Program.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace ex_031_005_LINQ_operators +{ + public class Program + { + public static void Main(string[] args) + { + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/Nounours.cs new file mode 100644 index 0000000..9eadb3d --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/Nounours.cs @@ -0,0 +1,72 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_031_006_LINQ_filtering +{ + class Nounours : IEquatable + { + public Nounours(string nom, DateTime naissance) + { + Nom = nom; + Naissance = naissance; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + public override bool Equals(object obj) + { + //check null + if (object.ReferenceEquals(obj, null)) + { + return false; + } + + if (object.ReferenceEquals(this, obj)) + { + return true; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + return this.Equals(obj as Nounours); + } + + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + return $"{Nom} ({Naissance.ToString("d")})"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/Program.cs b/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/Program.cs new file mode 100644 index 0000000..5144273 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/Program.cs @@ -0,0 +1,113 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using static System.Console; + +namespace ex_031_006_LINQ_filtering +{ + class Program + { + static void Main(string[] args) + { + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16)), + new Nounours("ours", new DateTime(2009, 08, 15)), + new Nounours("chat", new DateTime(2009, 07, 14)), + new Nounours("chien", new DateTime(2009, 06, 13)), + new Nounours("lapin", new DateTime(2009, 05, 12)), + new Nounours("chat", new DateTime(2009, 07, 14)), + new Nounours("macaque", new DateTime(2009, 04, 11))}; + + ///////////// + //Filtering// + ///////////// + WriteLine("Filtering"); + + //Where : condition + WriteLine("Where"); + IEnumerable filtered = nounours.Where(n => n.Nom.StartsWith("c")); + foreach (Nounours n in filtered) + { + WriteLine($"{n} "); + } + WriteLine(); + + //la même requête en query syntax + WriteLine("Where"); + IEnumerable filteredQuerySyntax = from n in nounours + where n.Nom.StartsWith("c") + select n; + foreach (Nounours n in filteredQuerySyntax) + { + WriteLine($"{n} "); + } + WriteLine(); + + //Take : prend les n premiers + WriteLine("Take"); + IEnumerable taken = nounours.Take(3); + foreach (Nounours n in taken) + { + WriteLine($"{n} "); + } + WriteLine(); + + //TakeWhile : prend les premiers tant qu'une condition est vérifiée + WriteLine("TakeWhile"); + IEnumerable takenwhile = nounours.TakeWhile(n => n.Naissance.Month > 6); + foreach (Nounours n in takenwhile) + { + WriteLine($"{n} "); + } + WriteLine(); + + //Skip : évite les n premiers + WriteLine("Skip"); + IEnumerable skipped = nounours.Skip(3); + foreach (Nounours n in skipped) + { + WriteLine($"{n} "); + } + WriteLine(); + + //SkipWhile : évite les premiers tant qu'une condition est vérifiée + WriteLine("SkipWhile"); + IEnumerable skippedwhile = nounours.SkipWhile(n => n.Naissance.Month > 7); + foreach (var n in skippedwhile) + { + WriteLine($"{n} "); + } + WriteLine(); + + //Distinct : retire les doublons + //ATTENTION ! utilise le protocole d'égalité ! sinon, compare les références + WriteLine("Distinct"); + IEnumerable distinct = nounours.Distinct(); + foreach (var n in distinct) + { + WriteLine($"{n} "); + } + WriteLine(); + + //Where : variante avec index + WriteLine("Where, variante avec index"); + IEnumerable filteredIndexedWhere = nounours.Where((n, i) => i % 2 == 0); + foreach (Nounours n in filteredIndexedWhere) + { + WriteLine($"{n} "); + } + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/ex_031_006_LINQ_filtering.csproj b/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/ex_031_006_LINQ_filtering.csproj new file mode 100644 index 0000000..fad38fd --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_006_LINQ_filtering/ex_031_006_LINQ_filtering.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_006_LINQ_filtering + Exe + ex_031_006_LINQ_filtering + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/Nounours.cs new file mode 100644 index 0000000..b4bc5d7 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/Nounours.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_031_007_LINQ_ordering +{ + class Nounours : IEquatable + { + public Nounours(string nom, DateTime naissance, int nbPoils) + { + Nom = nom; + Naissance = naissance; + NbPoils = nbPoils; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + public override bool Equals(object obj) + { + //check null + if (object.ReferenceEquals(obj, null)) + { + return false; + } + + if (object.ReferenceEquals(this, obj)) + { + return true; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + return this.Equals(obj as Nounours); + } + + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + return $"{Nom} ({Naissance.ToString("d")}, {NbPoils} poils)"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/NounoursDateComparer.cs b/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/NounoursDateComparer.cs new file mode 100644 index 0000000..f3dc3ef --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/NounoursDateComparer.cs @@ -0,0 +1,26 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursDateComparer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_031_007_LINQ_ordering +{ + /// + /// Si on a besoin d'un autre compareur et qu'on n'a pas accès au code source, alors on utilise un IComparer générique externe + /// + class NounoursDateComparer : IComparer + { + public int Compare(Nounours x, Nounours y) + { + return x.Naissance.CompareTo(y.Naissance); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/Program.cs b/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/Program.cs new file mode 100644 index 0000000..1e756e2 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/Program.cs @@ -0,0 +1,116 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using static System.Console; + +namespace ex_031_007_LINQ_ordering +{ + class Program + { + static void Main(string[] args) + { + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16), 1000), + new Nounours("ours", new DateTime(2009, 08, 15), 2000), + new Nounours("chat", new DateTime(2009, 07, 14), 1000), + new Nounours("chien", new DateTime(2009, 06, 13), 500), + new Nounours("lapin", new DateTime(2009, 05, 12), 500), + new Nounours("chat", new DateTime(2009, 07, 14), 2000), + new Nounours("macaque", new DateTime(2009, 04, 11), 500)}; + + //////////// + //Ordering// + //////////// + WriteLine("Ordering"); + + //OrderBy + WriteLine("OrderBy"); + IEnumerable ordered = nounours.OrderBy(n => n.Nom); + foreach (Nounours n in ordered) + { + WriteLine(n); + } + WriteLine(); + + //OrderBy en query syntax + WriteLine("OrderBy"); + IEnumerable orderedQS = from n in nounours + orderby n.Nom + select n; + foreach (Nounours n in orderedQS) + { + WriteLine(n); + } + WriteLine(); + + //OrderBy + ThenBy + WriteLine("OrderBy + ThenBy"); + IEnumerable orderedThenBy = nounours.OrderBy(n => n.NbPoils).ThenBy(n => n.Nom); + foreach (Nounours n in orderedThenBy) + { + WriteLine(n); + } + WriteLine(); + + //OrderBy + ThenBy en Query Syntax + WriteLine("OrderBy + ThenBy"); + IEnumerable orderedThenByQS = from n in nounours + orderby n.NbPoils, n.Nom + select n; + foreach (Nounours n in orderedThenByQS) + { + WriteLine(n); + } + WriteLine(); + + //OrderBy + OrderBy : ATTENTION ! NE FAIT PAS CE QU'ON ATTEND DE LUI + WriteLine("OrderBy + OrderBy : le 2ème orderby casse le premier"); + IEnumerable orderedOrderBy = nounours.OrderBy(n => n.NbPoils).OrderBy(n => n.Nom); + foreach (Nounours n in orderedOrderBy) + { + WriteLine(n); + } + WriteLine(); + + //OrderByDescending et ThenByDescending + WriteLine("OrderByDescending + ThenByDescending"); + IEnumerable orderedByDescendingThenByDescending = nounours.OrderByDescending(n => n.NbPoils).ThenByDescending(n => n.Nom); + foreach (Nounours n in orderedByDescendingThenByDescending) + { + WriteLine(n); + } + WriteLine(); + + //OrderByDescending et ThenByDescending en Query Syntax + WriteLine("OrderByDescending + ThenByDescending"); + IEnumerable orderedByDescendingThenByDescendingQS = from n in nounours + orderby n.NbPoils descending, n.Nom descending + select n; + foreach (Nounours n in orderedByDescendingThenByDescendingQS) + { + WriteLine(n); + } + WriteLine(); + + //OrderBy + comparer + WriteLine("OrderBy + Comparer"); + IEnumerable orderedCompared = nounours.OrderBy(n => n, new NounoursDateComparer()); + foreach (Nounours n in orderedCompared) + { + WriteLine(n); + } + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/ex_031_007_LINQ_ordering.csproj b/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/ex_031_007_LINQ_ordering.csproj new file mode 100644 index 0000000..3cac141 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_007_LINQ_ordering/ex_031_007_LINQ_ordering.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_007_LINQ_ordering + Exe + ex_031_007_LINQ_ordering + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/Nounours.cs new file mode 100644 index 0000000..8e4d21b --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/Nounours.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_031_008_LINQ_projecting +{ + class Nounours : IEquatable + { + public Nounours(string nom, DateTime naissance, int nbPoils) + { + Nom = nom; + Naissance = naissance; + NbPoils = nbPoils; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + public override bool Equals(object obj) + { + //check null + if (object.ReferenceEquals(obj, null)) + { + return false; + } + + if (object.ReferenceEquals(this, obj)) + { + return true; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + return this.Equals(obj as Nounours); + } + + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + return $"{Nom} ({Naissance.ToString("d")}, {NbPoils} poils)"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/Program.cs b/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/Program.cs new file mode 100644 index 0000000..ec6a364 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/Program.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using static System.Console; +using System.Text; +using System.Threading.Tasks; + +namespace ex_031_008_LINQ_projecting +{ + class Program + { + static void Main(string[] args) + { + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16), 1000), + new Nounours("ours", new DateTime(2009, 08, 15), 2000), + new Nounours("chat", new DateTime(2009, 07, 14), 1000), + new Nounours("chien", new DateTime(2009, 06, 13), 500), + new Nounours("lapin", new DateTime(2009, 05, 12), 500), + new Nounours("chat", new DateTime(2009, 07, 14), 2000), + new Nounours("macaque", new DateTime(2009, 04, 11), 500)}; + + ////////////// + //Projecting// + ////////////// + WriteLine("Projecting"); + + ////////////// + //SELECT // + ////////////// + + //Select : chaque élément d'un type T1 est transformé en un autre élément d'un type T2 + //Dans cet exemple, chaque nounours est transformé en un entier correspondant au nombre de lettres dans le nom du Nounours (ok ça ne sert à rien...) + WriteLine("Select"); + IEnumerable selected = nounours.Select(n => n.Nom.Length); + foreach (int i in selected) + { + WriteLine(i); + } + WriteLine(); + + //idem en Query Syntax + WriteLine("Select"); + IEnumerable selectedQS = from n in nounours + select n.Nom.Length; + foreach (int i in selectedQS) + { + WriteLine(i); + } + WriteLine(); + + //Select : avec un type anonyme + WriteLine("Select + type anonyme"); + var selectedAnonymous = nounours.Select(n => new { Nom = n.Nom, AnnéeNaissance = n.Naissance.Year, MoisNaissance = n.Naissance.Month, TailleDuNom = n.Nom.Length }); + foreach (var a in selectedAnonymous) + { + WriteLine(a); + } + WriteLine(); + + //Select : avec un type anonyme + WriteLine("Select + type anonyme"); + var selectedAnonymousQS = from n in nounours + select new { Nom = n.Nom, AnnéeNaissance = n.Naissance.Year, MoisNaissance = n.Naissance.Month, TailleDuNom = n.Nom.Length }; + foreach (var a in selectedAnonymousQS) + { + WriteLine(a); + } + WriteLine(); + + //indexed projection + WriteLine("Select + index"); + var selectedIndexed = nounours.Select((n, i) => $"{i + 1}. {n.Nom}"); + foreach (var s in selectedIndexed) + { + WriteLine(s); + } + WriteLine(); + + + ////////////// + //SELECTMANY// + ////////////// + + //SelectMany concatène des séquences en une seule séquence + //SelectMany peut donc être utilisé pour : + // - applatir des collections imbriquées + // - rejoindre deux collections en une seule séquence + + //SelectMany : exemple 1 : applatir des collections + WriteLine("SelectMany"); + string[] phrases = { @"Le premier lundi du mois d'avril 1625, le bourg de Meung, où naquit l'auteur du Roman de la Rose, + semblait être dans une révolution aussi entière que si les huguenots en fussent venus faire une seconde Rochelle.", + @"Plusieurs bourgeois, voyant s'enfuir les femmes du côté de la Grand-Rue, entendant les enfants crier sur le seuil des portes, + se hâtaient d'endosser la cuirasse, et, appuyant leur contenance quelque peu incertaine d'un mousquet ou d'une pertuisane, + se dirigeaient vers l'Hôtellerie du Franc - Meunier, devant laquelle s'empressait, en grossissant de minute en minute, un groupe compact, + bruyant et plein de curiosité.", + @"Arrivé là, chacun put voir et reconnaître la cause de cette humeur.", + @"Un jeune homme... traçons son portrait d'un seul trait de plume : figurez- vous don Quichotte à dix-huit ans ; don Quichotte décorselé, + sans haubert et sans cuissards ; don Quichotte revêtu d'un pourpoint de laine dont la couleur bleue s'était transformée en une nuance insaisissable de lie de vin + et d'azur céleste. Visage long et brun ; la pommette des joues saillante, signe d'astuce ; les muscles maxillaires énormément développés, + indice infaillible auquel on reconnaît le Gascon, même sans béret, et notre jeune homme portait un béret orné d'une espèce de plume ; + l'oeil ouvert et intelligent ; le nez crochu, mais finement dessiné ; trop grand pour un adolescent, trop petit pour un homme fait, + et qu'un oeil peu exercé eût pris pour un fils de fermier en voyage, sans la longue épée qui, pendue à un baudrier de peau, + battait les mollets de son propriétaire quand il était à pied, et le poil hérissé de sa monture quand il était à cheval.", + @"Car notre jeune homme avait une monture, et cette monture était même si remarquable, qu'elle fut remarquée : c'était un bidet du Béarn, + âgé de douze ou quatorze ans, jaune de robe, sans crins à la queue, mais non pas sans javarts aux jambes, et qui, tout en marchant la tête plus bas que les genoux, + ce qui rendait inutile l'application de la martingale, faisait encore également ses huit lieues par jour.", + @"Malheureusement les qualités de ce cheval étaient si bien cachées sous son poil étrange et son allure incongrue, + que dans un temps où tout le monde se connaissait en chevaux, l'apparition du susdit bidet à Meung, + où il était entré il y avait un quart d'heure à peu près par la porte de Beaugency, produisit une sensation dont la défaveur rejaillit jusqu'à son cavalier." }; + + var avecSelect = phrases.Select(phrase => phrase.Split()); + foreach (var p in avecSelect) + { + WriteLine(p); + } + + var avecSelectMany = phrases.SelectMany(phrase => phrase.ToLower().Split()) + .Where(mot => !String.IsNullOrWhiteSpace(mot)) + .Distinct() + .OrderBy(mot => mot); + foreach (var p in avecSelectMany) + { + WriteLine(p); + } + + //SelectMany : cross product avec un selectmany en query syntax + WriteLine("SelectMany et cross product"); + var affrontements = from n1 in nounours + from n2 in nounours + where n1.Nom != n2.Nom + select $"{n1.Nom} vs. {n2.Nom}"; + foreach (var a in affrontements) + { + WriteLine(a); + } + + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/ex_031_008_LINQ_projecting.csproj b/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/ex_031_008_LINQ_projecting.csproj new file mode 100644 index 0000000..532f9f2 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_008_LINQ_projecting/ex_031_008_LINQ_projecting.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_008_LINQ_projecting + Exe + ex_031_008_LINQ_projecting + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/Nounours.cs new file mode 100644 index 0000000..6d426bd --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/Nounours.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_031_009_LINQ_element_operators +{ + class Nounours : IEquatable + { + public Nounours(string nom, DateTime naissance, int nbPoils) + { + Nom = nom; + Naissance = naissance; + NbPoils = nbPoils; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + public override bool Equals(object obj) + { + //check null + if (object.ReferenceEquals(obj, null)) + { + return false; + } + + if (object.ReferenceEquals(this, obj)) + { + return true; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + return this.Equals(obj as Nounours); + } + + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + return $"{Nom} ({Naissance.ToString("d")}, {NbPoils} poils)"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/Program.cs b/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/Program.cs new file mode 100644 index 0000000..6e58bed --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/Program.cs @@ -0,0 +1,129 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using static System.Console; +using System.Linq; + +namespace ex_031_009_LINQ_element_operators +{ + class Program + { + static void Main(string[] args) + { + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16), 1000), + new Nounours("ours", new DateTime(2009, 08, 15), 2000), + new Nounours("chat", new DateTime(2009, 07, 14), 1000), + new Nounours("chien", new DateTime(2009, 06, 13), 500), + new Nounours("lapin", new DateTime(2009, 05, 12), 500), + new Nounours("chat", new DateTime(2009, 07, 14), 2000), + new Nounours("macaque", new DateTime(2009, 04, 11), 500)}; + + List nounoursVide = new List(); + + ///////////////////// + //Element Operators// + ///////////////////// + WriteLine("Element Operators"); + + //First : lève une exception si aucun élément n'est trouvé ou si la collection est vide + WriteLine("First"); + WriteLine(nounours.First()); + WriteLine(nounours.First(n => n.Nom.Equals("chat"))); + try + { + WriteLine(nounoursVide.First()); + } + catch (InvalidOperationException exc) + { + WriteLine($"{exc.ToString()}"); + } + WriteLine(); + + //First or default : ne lance pas d'exception si aucun élément ne vérifie la condition ou si la collection est vide + WriteLine("First or default"); + WriteLine(nounours.FirstOrDefault()); + WriteLine(nounours.FirstOrDefault(n => n.Nom.Equals("chat"))); + WriteLine(nounoursVide.FirstOrDefault()); + WriteLine(); + + //Last : lève une exception si aucun élément n'est trouvé ou si la collection est vide + WriteLine("Last"); + WriteLine(nounours.Last()); + WriteLine(nounours.Last(n => n.Nom.Equals("chat"))); + try + { + WriteLine(nounoursVide.Last()); + } + catch (InvalidOperationException exc) + { + WriteLine($"{exc.ToString()}"); + } + WriteLine(); + + //Last or default : ne lance pas d'exception si aucun élément ne vérifie la condition + WriteLine("Last or default"); + WriteLine(nounours.LastOrDefault()); + WriteLine(nounours.LastOrDefault(n => n.Nom.Equals("chat"))); + WriteLine(nounoursVide.LastOrDefault()); + WriteLine(); + + //Single : lance une exception s'il n'y a pas un seul élément vérifiant la condition + WriteLine("Single"); + WriteLine(nounours.Single(n => n.Nom.Equals("ours"))); + try + { + WriteLine(nounoursVide.Single()); + } + catch (InvalidOperationException exc) + { + WriteLine($"{exc.ToString()}"); + } + WriteLine(); + + //Single or default : lève une exception si plusieurs éléments vérifient la condition + WriteLine("Single or default"); + try + { + WriteLine(nounours.SingleOrDefault()); + } + catch (InvalidOperationException exc) + { + WriteLine($"{exc.ToString()}"); + } + WriteLine(nounours.SingleOrDefault(n => n.Nom.Equals("ours"))); + WriteLine(nounoursVide.SingleOrDefault()); + WriteLine(); + WriteLine(nounours.Single(n => n.Nom.Length == nounours.Max(n2 => n2.Nom.Length))); + WriteLine(); + + //ElementAt : lance une exception s'il n'y a pas d'élément à la position demandée + WriteLine("ElementAt"); + WriteLine(nounours.ElementAt(2)); + try + { + WriteLine(nounours.ElementAt(100)); + } + catch (ArgumentOutOfRangeException exc) + { + WriteLine($"{exc.ToString()}"); + } + WriteLine(); + + //ElementAt or default : lève une exception si plusieurs éléments vérifient la condition + WriteLine("ElementAt or default"); + WriteLine(nounours.ElementAtOrDefault(100)); + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/ex_031_009_LINQ_element_operators.csproj b/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/ex_031_009_LINQ_element_operators.csproj new file mode 100644 index 0000000..f1f459c --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_009_LINQ_element_operators/ex_031_009_LINQ_element_operators.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_009_LINQ_element_operators + Exe + ex_031_009_LINQ_element_operators + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/Nounours.cs new file mode 100644 index 0000000..a872175 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/Nounours.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using System; + +namespace ex_031_010_LINQ_aggregation_methods +{ + class Nounours : IEquatable + { + public Nounours(string nom, DateTime naissance, int nbPoils) + { + Nom = nom; + Naissance = naissance; + NbPoils = nbPoils; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + public override bool Equals(object obj) + { + //check null + if (object.ReferenceEquals(obj, null)) + { + return false; + } + + if (object.ReferenceEquals(this, obj)) + { + return true; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + return this.Equals(obj as Nounours); + } + + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + return $"{Nom} ({Naissance.ToString("d")}, {NbPoils} poils)"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/Program.cs b/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/Program.cs new file mode 100644 index 0000000..70e95bc --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/Program.cs @@ -0,0 +1,80 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-03 +// +// ======================================================================== + +using static System.Console; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ex_031_010_LINQ_aggregation_methods +{ + class Program + { + static void Main(string[] args) + { + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16), 1000), + new Nounours("ours", new DateTime(2009, 08, 15), 2000), + new Nounours("chat", new DateTime(2009, 07, 14), 1000), + new Nounours("chien", new DateTime(2009, 06, 13), 500), + new Nounours("lapin", new DateTime(2009, 05, 12), 500), + new Nounours("chat", new DateTime(2009, 07, 14), 2000), + new Nounours("macaque", new DateTime(2009, 04, 11), 500)}; + + /////////////////////// + //Aggregation Methods// + /////////////////////// + WriteLine("Aggregation Methods"); + + //Count + WriteLine("Count"); + int nbNounours = nounours.Count(); + WriteLine($"{nbNounours} nounours dans la collection"); + int nbNounours2000poils = nounours.Count(n => n.NbPoils == 2000); + WriteLine($"{nbNounours2000poils} nounours de 2000 poils dans la collection"); + WriteLine(); + + //Min, Max + WriteLine("Min, Max"); + int[] numbers = { 8, 4, 13, 7, 4, 6, 7, 4 }; + int max = numbers.Max(); + WriteLine($"le plus grand nombre est {max}"); + int plusPetitNbPoils = nounours.Min(n => n.NbPoils); // avec une expression lambda, une projection est d'abord effectuée + WriteLine($"le plus petit nb de poils est : {plusPetitNbPoils}"); + WriteLine(); + + //Sum + WriteLine("Sum"); + int sum = numbers.Sum(); + WriteLine($"la somme des nombres est {sum}"); + int sumNbPoils = nounours.Sum(n => n.NbPoils); + WriteLine($"la somme des poils des nounours est : {sumNbPoils}"); + WriteLine(); + + //Average + WriteLine("Average"); + double avg = numbers.Average(); + WriteLine($"la moyenne des nombres est {avg:0.00}"); + double avgNbPoils = nounours.Average(n => n.NbPoils); + WriteLine($"la moyenne des poils des nounours est : {sumNbPoils}"); + WriteLine(); + + //Aggregate + WriteLine("Aggregate"); + int aggregate = numbers.Aggregate(0, (somme, i) => somme + i); + WriteLine($"la somme des nombres est {aggregate}"); + + string nomsDesNounours = nounours.Aggregate(String.Empty, (chaîne, n) => chaîne + $"{n.Nom}, "); + WriteLine(nomsDesNounours.Remove(nomsDesNounours.Length - 2)); + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/ex_031_010_LINQ_aggregation_methods.csproj b/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/ex_031_010_LINQ_aggregation_methods.csproj new file mode 100644 index 0000000..8f8b35d --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_010_LINQ_aggregation_methods/ex_031_010_LINQ_aggregation_methods.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_010_LINQ_aggregation_methods + Exe + ex_031_010_LINQ_aggregation_methods + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/Nounours.cs new file mode 100644 index 0000000..415700c --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/Nounours.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; + +namespace ex_031_011_LINQ_grouping +{ + class Nounours : IEquatable + { + public Nounours(string nom, DateTime naissance, int nbPoils) + { + Nom = nom; + Naissance = naissance; + NbPoils = nbPoils; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + public override bool Equals(object obj) + { + //check null + if (object.ReferenceEquals(obj, null)) + { + return false; + } + + if (object.ReferenceEquals(this, obj)) + { + return true; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + return this.Equals(obj as Nounours); + } + + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + return $"{Nom} ({Naissance.ToString("d")}, {NbPoils} poils)"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/Program.cs b/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/Program.cs new file mode 100644 index 0000000..c57af62 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/Program.cs @@ -0,0 +1,99 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using static System.Console; + +namespace ex_031_011_LINQ_grouping +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.UTF8; + + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16), 1000), + new Nounours("ours", new DateTime(2009, 08, 15), 2000), + new Nounours("chat", new DateTime(2009, 07, 14), 1000), + new Nounours("chien", new DateTime(2009, 06, 13), 500), + new Nounours("lapin", new DateTime(2009, 05, 12), 500), + new Nounours("chat", new DateTime(2009, 07, 14), 2000), + new Nounours("macaque", new DateTime(2009, 04, 11), 500)}; + //////////// + //Grouping// + //////////// + + //GroupBy : groupe les éléments en fonction d'un critère + WriteLine("GroupBy avec un keySelector"); + IEnumerable> query + = nounours.GroupBy(n => n.Nom[0]).OrderBy(group => group.Key); + foreach (IGrouping group in query) + { + WriteLine($"nounours commençant par la lettre {group.Key} :"); + foreach (Nounours n in group) + { + WriteLine($"\t{n}"); + } + } + WriteLine(); + + //GroupBy avec Query Syntax + WriteLine("GroupBy avec un keySelector"); + IEnumerable> queryQS = from n in nounours + group n by n.Nom[0] into grouping + orderby grouping.Key + select grouping; + foreach (IGrouping group in queryQS) + { + WriteLine($"nounours commençant par la lettre {group.Key} :"); + foreach (Nounours n in group) + { + WriteLine($"\t{n}"); + } + } + WriteLine(); + + //GroupBy : avec keySelector et elementSelector + WriteLine("GroupBy avec keySelector et elementSelector"); + IEnumerable> query2 + = nounours.GroupBy(n => n.NbPoils, n => n.Nom).OrderBy(group => group.Key); + foreach (IGrouping group in query2) + { + WriteLine($"nounours de {group.Key} poils :"); + foreach (string s in group) + { + WriteLine($"\t{s}"); + } + } + WriteLine(); + + //GroupBy : avec keySelector et elementSelector avec Query Syntax + WriteLine("GroupBy avec keySelector et elementSelector"); + IEnumerable> query2QS = from n in nounours + group n.Nom by n.NbPoils into grouping + orderby grouping.Key + select grouping; + foreach (IGrouping group in query2QS) + { + WriteLine($"nounours de {group.Key} poils :"); + foreach (string s in group) + { + WriteLine($"\t{s}"); + } + } + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/ex_031_011_LINQ_grouping.csproj b/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/ex_031_011_LINQ_grouping.csproj new file mode 100644 index 0000000..898c6c2 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_011_LINQ_grouping/ex_031_011_LINQ_grouping.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_011_LINQ_grouping + Exe + ex_031_011_LINQ_grouping + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Enfant.cs b/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Enfant.cs new file mode 100644 index 0000000..2d592d0 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Enfant.cs @@ -0,0 +1,34 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Enfant.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ex_031_012_LINQ_joining +{ + class Enfant + { + public string Prénom + { + get; + set; + } + + public string NounoursPréféré + { + get; + set; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Nounours.cs new file mode 100644 index 0000000..1d5a527 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Nounours.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; + +namespace ex_031_012_LINQ_joining +{ + class Nounours : IEquatable + { + public Nounours(string nom, DateTime naissance, int nbPoils) + { + Nom = nom; + Naissance = naissance; + NbPoils = nbPoils; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + public override bool Equals(object obj) + { + //check null + if (object.ReferenceEquals(obj, null)) + { + return false; + } + + if (object.ReferenceEquals(this, obj)) + { + return true; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + return this.Equals(obj as Nounours); + } + + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + return $"{Nom} ({Naissance.ToString("d")}, {NbPoils} poils)"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Program.cs b/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Program.cs new file mode 100644 index 0000000..8b30d2b --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/Program.cs @@ -0,0 +1,72 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using static System.Console; + +namespace ex_031_012_LINQ_joining +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.UTF8; + + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16), 1000), + new Nounours("ours", new DateTime(2009, 08, 15), 2000), + new Nounours("chien", new DateTime(2009, 06, 13), 500), + new Nounours("lapin", new DateTime(2009, 05, 12), 500), + new Nounours("chat", new DateTime(2009, 07, 14), 2000), + new Nounours("macaque", new DateTime(2009, 04, 11), 500)}; + + List enfants = new List { + new Enfant {Prénom="Ulysse", NounoursPréféré = "chat" }, + new Enfant {Prénom="Télémaque", NounoursPréféré = "lapin" }, + new Enfant {Prénom="Pénélope", NounoursPréféré = "chien" } }; + //////////// + //Joining // + //////////// + + //Join : applique une stratégie de recherche pour faire correspondre des éléments de deux collections + WriteLine("Join"); + var joined = nounours.Join(enfants, n => n.Nom, e => e.NounoursPréféré, (n, e) => new { Nounours = n.Nom, Enfant = e.Prénom }); + foreach (var j in joined) + { + WriteLine(j); + } + WriteLine(); + + //Join en Query Syntax + WriteLine("Join"); + var joinedQS = from n in nounours + join e in enfants on n.Nom equals e.NounoursPréféré + select new { Nounours = n.Nom, Enfant = e.Prénom }; + foreach (var j in joinedQS) + { + WriteLine(j); + } + WriteLine(); + + //Zip operator : la fermeture éclair ! + string[] nombresEnLettres = { "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf" }; + int[] nombres = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + var nombresEnChiffresEtEnLettres = nombres.Zip(nombresEnLettres, (i, s) => $"{i}. {s}"); + foreach (var s in nombresEnChiffresEtEnLettres) + { + WriteLine(s); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/ex_031_012_LINQ_joining.csproj b/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/ex_031_012_LINQ_joining.csproj new file mode 100644 index 0000000..e4df53a --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_012_LINQ_joining/ex_031_012_LINQ_joining.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_012_LINQ_joining + Exe + ex_031_012_LINQ_joining + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_013_LINQ_set_operators/Program.cs b/p06_MoreAdvancedCSharp/ex_031_013_LINQ_set_operators/Program.cs new file mode 100644 index 0000000..2160adb --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_013_LINQ_set_operators/Program.cs @@ -0,0 +1,73 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System.Collections.Generic; +using System.Linq; +using static System.Console; + +namespace ex_031_013_LINQ_set_operators +{ + class Program + { + static void Main(string[] args) + { + ///////////////// + //set operators// + ///////////////// + WriteLine("Set operators"); + + int[] séquence1 = { 1, 2, 3 }; + int[] séquence2 = { 3, 4, 5 }; + + //Concat : tous les éléments de la séquence 1, puis tous les éléments de la séquence 2 + WriteLine("Concat"); + IEnumerable concat = séquence1.Concat(séquence2); + foreach (int n in concat) + { + Write($"{n} "); + } + WriteLine(); + + //Union : tous les éléments de la séquence 1, puis tous les éléments de la séquence 2 (sans doublons) + WriteLine("Union"); + IEnumerable union = séquence1.Union(séquence2); + foreach (int n in union) + { + Write($"{n} "); + } + WriteLine(); + + //Intersect : tous les éléments qui sont dans la séquence 1 ET dans la séquence 2 + WriteLine("Intersect"); + IEnumerable intersect = séquence1.Intersect(séquence2); + foreach (int n in intersect) + { + Write($"{n} "); + } + WriteLine(); + + //Except : tous les éléments de la séquence 1 SAUF ceux qui sont aussi dans la séquence 2 + WriteLine("Except"); + IEnumerable except = séquence1.Except(séquence2); + foreach (int n in except) + { + Write($"{n} "); + } + WriteLine(); + IEnumerable except2 = séquence2.Except(séquence1); + foreach (int n in except2) + { + Write($"{n} "); + } + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_013_LINQ_set_operators/ex_031_013_LINQ_set_operators.csproj b/p06_MoreAdvancedCSharp/ex_031_013_LINQ_set_operators/ex_031_013_LINQ_set_operators.csproj new file mode 100644 index 0000000..c224007 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_013_LINQ_set_operators/ex_031_013_LINQ_set_operators.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_013_LINQ_set_operators + Exe + ex_031_013_LINQ_set_operators + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_014_LINQ_quantifiers/Program.cs b/p06_MoreAdvancedCSharp/ex_031_014_LINQ_quantifiers/Program.cs new file mode 100644 index 0000000..a774702 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_014_LINQ_quantifiers/Program.cs @@ -0,0 +1,53 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using static System.Console; +using System.Linq; + +namespace ex_031_014_LINQ_quantifiers +{ + class Program + { + static void Main(string[] args) + { + ///////////////// + //quantifiers // + ///////////////// + WriteLine("Quantifiers"); + + int[] séquence1 = { 2, 4, 6 }; + int[] séquence2 = { 3, 6, 9 }; + + //Contains : retourne true si la collection contient l'élément donné + WriteLine("Contains"); + Write(séquence1.Contains(2) ? "true" : "false"); + Write(séquence2.Contains(2) ? "true" : "false"); + WriteLine(); + + //Any : retourne true si au moins 1 élément de la collection vérifie le prédicat + WriteLine("Any"); + Write(séquence1.Any(i => i % 2 == 0) ? "true" : "false"); + Write(séquence2.Any(i => i % 2 == 0) ? "true" : "false"); + Write(séquence2.Where(i => i % 2 == 0).Any() ? "true" : "false"); + WriteLine(); + + //All : retourne true si tous les éléments de la collection vérifient le prédicat + WriteLine("Any"); + Write(séquence2.All(i => i % 2 == 0) ? "true" : "false"); + Write(séquence2.All(i => i % 3 == 0) ? "true" : "false"); + WriteLine(); + + //SequenceEqual : retourne true si les deux collections contiennent le même nombre d'éléments, égaux, et dans le même ordre + WriteLine("SequenceEqual"); + Write(Enumerable.SequenceEqual(séquence1, séquence2) ? "true" : "false"); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_014_LINQ_quantifiers/ex_031_014_LINQ_quantifiers.csproj b/p06_MoreAdvancedCSharp/ex_031_014_LINQ_quantifiers/ex_031_014_LINQ_quantifiers.csproj new file mode 100644 index 0000000..d81e87a --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_014_LINQ_quantifiers/ex_031_014_LINQ_quantifiers.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_036.0.6_LINQ_quantifiers + Exe + ex_036.0.6_LINQ_quantifiers + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_015_LINQ_generation_methods/Program.cs b/p06_MoreAdvancedCSharp/ex_031_015_LINQ_generation_methods/Program.cs new file mode 100644 index 0000000..0d40871 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_015_LINQ_generation_methods/Program.cs @@ -0,0 +1,39 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using static System.Console; +using System.Linq; + +namespace ex_031_015_LINQ_generation_methods +{ + class Program + { + static void Main(string[] args) + { + //////////////////////// + //generation methods // + //////////////////////// + WriteLine("Generation methods"); + + //Range : prend une valeur de démarrage et un nombre de valeurs pour générer la collection + WriteLine("Range"); + var ranged = Enumerable.Range(3, 4); + foreach (var i in ranged) Write($"{i} "); + WriteLine(); + + //Repeat : prend une valeur à répéter et le nombre de répétitions pour générer la collection + WriteLine("Repeat"); + var repeated = Enumerable.Repeat(3, 4); + foreach (var i in repeated) Write($"{i} "); + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_015_LINQ_generation_methods/ex_031_015_LINQ_generation_methods.csproj b/p06_MoreAdvancedCSharp/ex_031_015_LINQ_generation_methods/ex_031_015_LINQ_generation_methods.csproj new file mode 100644 index 0000000..a5b90cb --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_015_LINQ_generation_methods/ex_031_015_LINQ_generation_methods.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_015_LINQ_generation_methods + Exe + ex_031_015_LINQ_generation_methods + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/Nounours.cs b/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/Nounours.cs new file mode 100644 index 0000000..7638197 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/Nounours.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; + +namespace ex_031_016_LINQ_conversion_methods +{ + class Nounours : IEquatable + { + public Nounours(string nom, DateTime naissance, int nbPoils) + { + Nom = nom; + Naissance = naissance; + NbPoils = nbPoils; + } + + public string Nom + { + get; + private set; + } + + public DateTime Naissance + { + get; + private set; + } + + public int NbPoils + { + get; + private set; + } + + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + public override bool Equals(object obj) + { + //check null + if (object.ReferenceEquals(obj, null)) + { + return false; + } + + if (object.ReferenceEquals(this, obj)) + { + return true; + } + + if (this.GetType() != obj.GetType()) + { + return false; + } + + return this.Equals(obj as Nounours); + } + + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + return $"{Nom} ({Naissance.ToString("d")}, {NbPoils} poils)"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/Program.cs b/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/Program.cs new file mode 100644 index 0000000..f921bbd --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/Program.cs @@ -0,0 +1,66 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using static System.Console; +using System.Linq; +using System.Collections.Generic; +using System; + +namespace ex_031_016_LINQ_conversion_methods +{ + class Program + { + static void Main(string[] args) + { + //////////////////////// + //conversion methods // + //////////////////////// + WriteLine("Conversion methods"); + + //Cast : convertit une collection en une collection d'un certain type, si possible (sinon exception) + //utile pour convertir une collection non typée en une collection typée + WriteLine("Cast"); + List trucs = new List { 1, 2, 3 }; + IEnumerable entiers = trucs.Cast(); + foreach (int i in entiers) Write($"{i} "); + WriteLine(); + WriteLine(); + + //ToArray, ToList : convertit en tableau ou en List + //ATTENTION : casse l'exécution différée + WriteLine("ToArray, ToList"); + int[] tabEntiers = entiers.ToArray(); + List listEntiers = entiers.ToList(); + foreach (var i in tabEntiers) Write($"{i} "); + WriteLine(); + foreach (var i in listEntiers) Write($"{i} "); + WriteLine(); + WriteLine(); + + //ToDictionary : permet de construire un dictionnaire à partir d'une collection en spécifiant la clé et la valeur à partir de chaque item + List nounours = new List { + new Nounours("mouton", new DateTime(2009, 09, 16), 1000), + new Nounours("ours", new DateTime(2009, 08, 15), 2000), + new Nounours("chien", new DateTime(2009, 06, 13), 500), + new Nounours("lapin", new DateTime(2009, 05, 12), 500), + new Nounours("chat", new DateTime(2009, 07, 14), 2000), + new Nounours("macaque", new DateTime(2009, 04, 11), 500)}; + WriteLine("ToDictionary"); + Dictionary dico1 = nounours.ToDictionary(n => n.Nom); + foreach (var kvp in dico1) WriteLine($"{kvp.Key} : {kvp.Value}"); + WriteLine(); + Dictionary dico2 = nounours.ToDictionary(n => n.Nom, n => n.NbPoils); + foreach (var kvp in dico2) WriteLine($"{kvp.Key} : {kvp.Value}"); + WriteLine(); + WriteLine(); + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/ex_031_016_LINQ_conversion_methods.csproj b/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/ex_031_016_LINQ_conversion_methods.csproj new file mode 100644 index 0000000..d75b64c --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_031_016_LINQ_conversion_methods/ex_031_016_LINQ_conversion_methods.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_031_016_LINQ_conversion_methods + Exe + ex_031_016_LINQ_conversion_methods + 6.0.6 + false + false + false + + diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/README.md b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/README.md new file mode 100644 index 0000000..cfb381b --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/README.md @@ -0,0 +1,57 @@ +## How to use reflection to explore an assembly? +or +## How to use reflection to dynamically add a plugin to an application? + +This sample is made of three projects. Be careful with the role and moreover, the links between each other. + +#### 1) ex_036_001_Mammifère.csproj +This assembly contains a **_Mammifère_** class with a simple **_Name_** property and compiles to a dll in the **_ex_036_001_Reflection\bin_** directory. +#### 2) ex_036_001_ChatChienOiseau.csproj +This assembly contains three classes: +- 2 of them are inheriting from **_Mammifère_** (**_Chat_** and **_Chien_**), +- the other one is not inheriting from **_Mammifère_** (**_Oiseau_**). + +Important: this assembly references the first one, and compiles to a dll into the **_ex_036_001_Reflection\plugin_** directory. +#### 3) Applications\ex_036_001_Reflection.csproj +This assembly compiles to an exe in the **_ex_036_001_Reflection\bin_** directory. It references the first assembly, but **_does not reference_** the second assembly. +- First, it parses the plugin folder and gets all files : +```` C# +DirectoryInfo folder = new DirectoryInfo(Directory.GetCurrentDirectory().ToString()+"..\\..\\..\\plugin\\");F +ileInfo[] files = folder.GetFiles(); +```` +- Next, it filters these files and launches an assembly analysis on .dll files only +```` C# +foreach (FileInfo file in files.Where(f => f.Extension.Equals(".dll"))) +{ + AnalyseDLL(file.FullName); +} +```` +- In this **_AnalyseDLL(string filePath)_** method, first, it loads the assembly: +```` C# +Assembly a = Assembly.LoadFile(filePath); +```` +- then, it gets all the exported types of this assembly (all public types): +```` C# +Type[] types = a.GetExportedTypes(); +```` +- for each type **_t_** in **_types_**, it then writes its name in the Console, and tests if it's a subclass of **_Animal.Mammifère_** +```` C# +Write(t.Name); + +if(t.GetTypeInfo().IsSubclassOf(typeof(Animal.Mammifère))) +{ + // +} +```` + + +Remember that this Console App does not reference the assembly where the classes **_Chat_**, **_Chien_** and **_Oiseau_** are defined. +It only references the first assembly with the **_Animal.Mammifère_** class, so +this is the only class it knows at compile-time. It _discovers_ the others by reflection. + +Now you can explore the types (if they are primitive, interfaces, abstract, delegate, generics ...) and their members (methods, properties...). +Have fun! + + + +_Marc Chevaldonné, 27th of may 2019_ diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/Applications/Program.cs b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/Applications/Program.cs new file mode 100644 index 0000000..e6526d0 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/Applications/Program.cs @@ -0,0 +1,76 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Reflection; +using Animal; +using System.Linq; +using static System.Console; + +namespace Reflection +{ + class Program + { + static void Main(string[] args) + { + //permet d'accéder au dossier courant (ici l'endroit où se trouve l'exécutable) + WriteLine(System.IO.Directory.GetCurrentDirectory()); + + DirectoryInfo folder = new DirectoryInfo(Directory.GetCurrentDirectory().ToString()+"..\\..\\..\\..\\plugin\\net5.0\\"); + FileInfo[] files = folder.GetFiles(); + + foreach (FileInfo file in files.Where(f => f.Extension.Equals(".dll"))) + { + AnalyseDLL(file.FullName); + } + } + + static void AnalyseDLL(string filePath) + { + //chargement d'une dll dans ce dossier courant + Assembly a = Assembly.LoadFile(filePath); + + //on récupère tous les types contenus dans cette dll dans un tableau "types" + Type[] types = a.GetExportedTypes(); + + //pour chacun de ces types : + foreach (Type t in types) + { + //on écrit le nom du type (nom d'une classe par exemple) + Write(t.Name); + + //teste si le type dérive de Mammifère ou non + if(t.GetTypeInfo().IsSubclassOf(typeof(Animal.Mammifère))) + { + //si le type dérive de Mammifère, on écrit le nom du type Mammifère entre parenthèses + Write(" (" + t.GetTypeInfo().BaseType.Name + ")\n"); + + //on appelle le constructeur du type (chat ou chien par exemple) et on le référence à l'aide d'une + //référence sur un Mammifère (chat et chien dérivent de mammifère) + Mammifère bitxo = Activator.CreateInstance(t) as Mammifère; + + //on affiche à l'écran le membre mName du type concerné (minou pour chat, toutou pour chien) + WriteLine(" je m'appelle : " + bitxo.Name); + } + else + { + //si le type ne dérive pas de Mammifère, alors on le dit + WriteLine(" ne dérive pas de Animal.Mammifère"); + } + WriteLine(); + } + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/Applications/ex_036_001_Reflection.csproj b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/Applications/ex_036_001_Reflection.csproj new file mode 100644 index 0000000..311cffb --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/Applications/ex_036_001_Reflection.csproj @@ -0,0 +1,34 @@ + + + + + net6.0 + ex_036.0.6_Reflection + Exe + ex_036.0.6_Reflection + 6.0.6 + false + false + false + + + + + ..\..\bin\debug + + + ..\..\bin\release + + + + + diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chat.cs b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chat.cs new file mode 100644 index 0000000..34c61f9 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chat.cs @@ -0,0 +1,25 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chat.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Animal +{ + public class Chat : Mammifère + { + public Chat() + { + Name = "minou"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chien.cs b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chien.cs new file mode 100644 index 0000000..c3e37de --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Chien.cs @@ -0,0 +1,25 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chien.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Animal +{ + public class Chien : Mammifère + { + public Chien() + { + Name = "toutou"; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Oiseau.cs b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Oiseau.cs new file mode 100644 index 0000000..631836c --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/Oiseau.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Oiseau.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Animal +{ + public class Oiseau + { + public Oiseau() + { + Name = "cuicui"; + } + + public string Name + { + get; + protected set; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/ex_036_001_ChatChienOiseau.csproj b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/ex_036_001_ChatChienOiseau.csproj new file mode 100644 index 0000000..539ddad --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/ChatChienOiseauDll/ex_036_001_ChatChienOiseau.csproj @@ -0,0 +1,34 @@ + + + + + net6.0 + ex_036.0.6_ChatChienOiseau + Library + ex_036.0.6_ChatChienOiseau + 6.0.6 + false + false + false + + + + + ..\..\plugin + + + ..\..\plugin + + + + + diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/MammifereDll/Mammifere.cs b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/MammifereDll/Mammifere.cs new file mode 100644 index 0000000..efd4838 --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/MammifereDll/Mammifere.cs @@ -0,0 +1,30 @@ +// ======================================================================== +// +// Copyright (C) 2013-2014 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Mammifere.cs +// Author : Marc Chevaldonné +// Creation date : 2014-05-26 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Animal +{ + public class Mammifère + { + public Mammifère() + { + } + + public string Name + { + get; + protected set; + } + } +} diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/MammifereDll/ex_036_001_Mammifere.csproj b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/MammifereDll/ex_036_001_Mammifere.csproj new file mode 100644 index 0000000..5fba01b --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/Solution/MammifereDll/ex_036_001_Mammifere.csproj @@ -0,0 +1,31 @@ + + + + + net6.0 + ex_036.0.6_Mammifere + Library + ex_036.0.6_Mammifere + 6.0.6 + false + false + false + + + + + ..\..\bin\debug + + + ..\..\bin\release + + diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_ChatChienOiseau.deps.json b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_ChatChienOiseau.deps.json new file mode 100644 index 0000000..51f3c4f --- /dev/null +++ b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_ChatChienOiseau.deps.json @@ -0,0 +1,36 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v6.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v6.0": { + "ex_036.0.6_ChatChienOiseau/1.0.0": { + "dependencies": { + "ex_036.0.6_Mammifere": "1.0.0" + }, + "runtime": { + "ex_036.0.6_ChatChienOiseau.dll": {} + } + }, + "ex_036.0.6_Mammifere/1.0.0": { + "runtime": { + "ex_036.0.6_Mammifere.dll": {} + } + } + } + }, + "libraries": { + "ex_036.0.6_ChatChienOiseau/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "ex_036.0.6_Mammifere/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + } + } +} \ No newline at end of file diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_ChatChienOiseau.dll b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_ChatChienOiseau.dll new file mode 100644 index 0000000000000000000000000000000000000000..a08cd077b03bdfba61a1bc1f98c7a82f98c522eb GIT binary patch literal 4608 zcmeHKU2GiH75-*zZ;gYEtpG|vkTFTX3CZr-PRwt?_O3%*Vmo*pr=Yg$+1=~)koj57 z%sRG8TUY!%B1ELB;sp>$t)i;pfd^WIR29Sv3Zep1kf5!2sw$!WNPTD@NWXJuHr};S zB&t3|ob{Z0{_eTwd~;{!dghU5&;g*6*Tsv#YaE5fHNQODpu2DPZ~E}+Rp$p^Gmf7h zTv)L~vmW@hz;exs<#~Q&mX#SaJk$2f!d%gG{i@3J_V(;eQlFRtjvE~qxG?)!bG1L? z7ITM@1A1sl$JSeiIGVi1c>(=ePQ`VLLF(7EK~B3+2bP|cQ2E;&6ID#4-`@tzi7?Le z0>oBY0*(KC@+i>M!zAo_H#N!`>mnZQye2!jeWUE4SX zX;cbop>bB936$eAP`j4slw7)RjtPwelTEofb_uQ|sV#*ryleuWbODAK{|8!34e_q= zFBLFFeQ1X$2U@JXZB~}6V{a5Imrdiq&8Z)7X6J!hQXN0k0w#;!o-~q*q`%d}nOtTx zH#&Tm6xaoayr2E<`4R9K$73QFqrmoRp+vkz%nowgbFzrPQx;hEJaBTlAWkm&iRhD# zUlyIj>Bgz+UNEi_mz0}u-v9S)}}ohYuviGG4eUBJ<+|NE6C~w zLL&4LI~*WSn{|5YH_6 zPTWa;BTkX;!4moH_$m1)ULwB-zru!|^@8S|x~4;nN%0;@uU+Jw8%?BGu%?3=^`-{q zAJIyTXVX5>6o7kY{A$Bd_u<}I%T@QCE|n&&%4u$`qqcIYsHvzV4unmixE@Bz&CEBv z$fjMbm2#tF+^}P%8OwF;WfdsI(wo1aSWx9gt)_y>z&{gOWk(ewD^ke&ZryfN@PP7E zKtpvR;)X6a=!$1Z=vG@xmQB}07%I2ytS{J6>x=~}VC_fwqE=`8;Pm$Rqg;Mb1)=SG z+nv+ivLCosM5pC!i;9ca-g)I%Yg!67vn1F^7+q!Cv7_}(@2cfA6xw0TBx?|NOnA0y zIjz9vSF9+%Vk>XX4wco&R2?Uo4{g4bOf5UAB1I!piTt2xFW6Si^TWulgiTXYVy1Z? ziYi#OD=JLTXC2%ZRAp(*l^U*Bb7W_)XRbCWk`P|mCRpt8ONN!{#>sD4m%dI;qJe2WNbf`jn zvh^GvWC5zWYIzk^%@+)KNn`VWN*WXJvi;q6eERu!mwVqi^SyryN(t?hkGt8_+Q;UH zKem>5?^)E0WqWW#X;kT_D4BC{AJc4wxjo<4+7*C+oF0H(JnptP6Q92LoNu#BoSYrM zGtP6CJirOPl{!pm5k-{9r!Y@xnkVg9>eJ*$<5M@@==|Fk@i$tYP@#CdKUVa4t0k?r z%DK&8Rto|1*gXF!=Jc@4x2n)yJ!^qpi`I~S3lZadYB9aixtB=|))X;H-pjQw%cNs+ zX#NhPOd0q-PYuSU_ySiC`SzAP^|o~sPi`g77{wS*EID3d)bm);^~h**u16$nW>B>9 z+d#_k{k@rgk)DA5&H9IvY?3jqXE);o0e*uR>oJo%8^k{1ZfHko s6C>~(DR@p0LqXZ)U36Hzd6_veu59VbCo}$^ap=w~ztyih+>XG10WMW%I{*Lx literal 0 HcmV?d00001 diff --git a/p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_Mammifere.dll b/p06_MoreAdvancedCSharp/ex_036_001_Reflection/plugin/net6.0/ex_036.0.6_Mammifere.dll new file mode 100644 index 0000000000000000000000000000000000000000..443b5eb50a96808e1652f422bc90f15414a55dd9 GIT binary patch literal 4096 zcmeHKU2GIp6h3$RL-{KZeuQ9fN(&UEv)dLbC_;a>g-Tm$cMFD>?dQ_!Y|r@cSwZW<8Ko0p`R!APs|ay=#AnCv?yEa!{$*xob+MP> zq;|{tSk0@7px)FAy(03=aZYa26MAQ&vwbITguQ{!!?gJ|q9+kQkLFb1nNGoHiyg?F z({CP6(Jm1DSey5b4<<1Wfxp3gujOVjGhn$mwDPo=&&;2qlU9X!@!rs>NVxYoS1#$o zh-SW`XPW4J5zh6rUHmNSXz&D z`UsePh90>d0+}47Q(}Xn1!8HTQH^chS$!2N1RV}JG|?t-S;f88uo>&viy$94UPX+{ zfa_@u@B-Qlyp-A%-l=ep!Y=}IELX)!8dP)>_0eT&qWyG@bW|Y@yqtCbucbr4&1fi{ zo~HMJJLxR&b99cn)v5`FV=9g|*u?Ow0at@x?TJd32vR{0aCD#*zm_^e1<|fyH($2o zZrU|s*mC!=Os3b!9mAs^Fr}5Jf($aOAiqMSru{(L`dHZsOvvR_Cehi2hU&@;8@6p8 zk)EWG`u1axNtrDd3exNK+~dBHwPY$V0!e+YT{11{?Uj!7AjtOwXt-<{s&ECH-Yu*0 zGOOzGeQ9T{>9iSCuSgpnVjsW@Q66`_WB1w*VEcp8^G(;eS2^e$aXs4zpfs#|tis@x zc1&8vl%o7uFHvpS463YYnZfj|cG9rQlIE6CkM=;_smC#G!@6%_^}J<8D`y~rrcrQQKQMECMHGdlS8AV<-lUn6epGSnja~qIAbS)Z!v@KIm+t!H#!vg- zJd^t(ziaIqRI3TmP@|Ek1F>uwvyF;uYdF6r^ZK&u3!aVDH^QK?rj;5SgnGdet>fdC zj;%W68Kn`|>7UBU5(k|wa$gA8%~J<+yP(zjNPoJ|^<+<}v^A>B^OI;XIA~lk^F))T zU$Ts8)trm4yd6D=A6_Yf>J&q?M$n4;HYnBdZrHUNer^5wB8lNqyjbW8#x2}ExA>lj zfUTEf@T>bA?yqxvcT|D8?yC5)R5CSHw2Q?vpZ0z*{>qixAFi2XAMtS?eHXV4FPAGy zv_sx?92rl#xw0*tz>nj6mEw76yM9Naqa$wTioRi&Ea|uDjttszs7<_-z=7i;qCGP<(;4xUYn8d$@tGrVs=)~Mq!dn|XeUF^&_}k&7ZlcrNuo0Y&Z3A_XQj`Ji zr!i22_|h5yKL|V!es$4TwYUEXZwc;5hH%~!GU~psa;v0#-wSv($b%mf-whHz9Xdj; z(zmEpX=n{dedrAeVCRAh;e0J$@B%RfureVp+{e?82t`n0=C_Tqpb5FGguJqI61)49 zQ+`Tw_K~>vGg#3{UAQw77+v6p5si(XiFhSeNflB8@26Rx2bIRJin%@Vz+S=_*1(># z4wS6}uNLaczS-l$?yXZE>-fuys1-#KG=#MU<*g4DE77#dtUyKVL^uLOhw+6W@cg)P z1yw!XyHXF1 + /// System.IO possède un ensemble de types pour gérer les fichiers, les dossiers et leurs chemins d'accès. + /// On trouve notamment : + /// - les classes statiques File et Directory + /// - les classes non statiques FileInfo et DirectoryInfo + /// - une classe Path permettant de construire les chemins d'accès. + /// L'exemple suivant montre comment : partir du chemin de sortie de ce projet (i.e. le dossier où se trouvera l'exécutable généré), + /// puis se diriger dans le dossier dans lequel se trouve le fichier Program.cs que vous lisez + /// puis utiliser les méthodes statiques de File et Directory pour vérifier que ce fichier existe. + /// Il montre aussi comment récupérer des informations, copier un fichier, déplacer un fichier, crypter et décrypter, etc... + /// + /// + static void Main(string[] args) + { + //Récupère le chemin du dossier courant (par défaut le dossier de sortie donné dans les propriétés du projet) + string currentDir = Directory.GetCurrentDirectory(); + WriteLine($"Le dossier courant est : {currentDir}"); + ReadKey(); + + //récupère le chemin du dossier parent + DirectoryInfo parentDir = Directory.GetParent(currentDir); + WriteLine($"Le dossier parent est : {parentDir.Name}, le chemin complet est {parentDir.FullName}"); + ReadKey(); + + //récupère le chemin d'un ancêtre + DirectoryInfo ancestorDir = new DirectoryInfo(Path.Combine(currentDir, "..//..//..//..//")); + WriteLine($"Le dossier ancêtre, quatre niveaux au-dessus, est : {ancestorDir.Name}, le chemin complet est {ancestorDir.FullName}"); + ReadKey(); + + //récupère l'ensemble des sous-dossiers de ce dossier + //string[] subDirectories = Directory.GetDirectories(ancestorDir.FullName); + //depuis C#4, la ligne ci-dessous est plus efficace que la ligne ci-dessus + IEnumerable subDirectories = Directory.EnumerateDirectories(ancestorDir.FullName); + WriteLine("les sous-dossiers de ce dossier sont :"); + foreach (string subDir in subDirectories) + { + WriteLine(Path.GetFileName(subDir)); + } + ReadKey(); + + //vérifie que le dossier ex_037_001_File_and_Directory_management existe + string dossierProjet = Path.Combine(ancestorDir.FullName, "ex_037_001_File_and_Directory_management"); + bool exist = Directory.Exists(dossierProjet); + WriteLine($"le dossier ex_037_001_File_and_Directory_management existe-t-il ? {(exist ? "oui" : "non")}"); + ReadKey(); + + //s'il existe, rentre dedans et liste l'ensemble des fichiers de ce dossier + if (exist) + { + WriteLine("Il contient les fichiers suivants :"); + //string[] files = Directory.GetFiles(dossierProjet); + //depuis C#4, la ligne ci-dessous est plus efficace que la ligne ci-dessous + IEnumerable files = Directory.EnumerateFiles(dossierProjet); + foreach (string f in files) + { + WriteLine(Path.GetFileName(f)); + } + ReadKey(); + + + WriteLine("Il contient les fichiers *.cs suivants :"); + //string[] files = Directory.GetFiles(dossierProjet); + //depuis C#4, la ligne ci-dessous est plus efficace que la ligne ci-dessous + IEnumerable filesCS = Directory.EnumerateFiles(dossierProjet, "*.cs"); + foreach (string f in filesCS) + { + WriteLine(Path.GetFileName(f)); + } + ReadKey(); + + WriteLine("on copie le fichier Program.cs en copie.cs"); + //on impose le dossier courant comme étant le dossierProjet + Directory.SetCurrentDirectory(dossierProjet); + //on copie le fichier Program.cs en l'appelant copie.cs dans le dossier courant + File.Copy(filesCS.First(), "copie.cs"); + ReadKey(); + + WriteLine("on supprime le fichier copie.cs"); + //on supprime le fichier "copie.cs" + File.Delete("copie.cs"); + } + + //et plein d'autres méthodes et propriétés que vous pouvez découvrir ! + } + } +} diff --git a/p07_Persistance/ex_037_001_File_and_Directory_management/ex_037_001_File_and_Directory_management.csproj b/p07_Persistance/ex_037_001_File_and_Directory_management/ex_037_001_File_and_Directory_management.csproj new file mode 100644 index 0000000..5d4f224 --- /dev/null +++ b/p07_Persistance/ex_037_001_File_and_Directory_management/ex_037_001_File_and_Directory_management.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_037_001_File_and_Directory_management + Exe + ex_037_001_File_and_Directory_management + 6.0.6 + false + false + false + + diff --git a/p07_Persistance/ex_037_002_FileStream/Program.cs b/p07_Persistance/ex_037_002_FileStream/Program.cs new file mode 100644 index 0000000..23ad721 --- /dev/null +++ b/p07_Persistance/ex_037_002_FileStream/Program.cs @@ -0,0 +1,130 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== +using System.IO; +using System.Linq; +using System.Text; +using static System.Console; + +namespace ex_037_002_FileStream +{ + class Program + { + /// + /// L'architecture des streams (flux) en .NET est basée sur trois concepts : + /// - les backing stores, i.e. un fichier, une connection réseau, une chambre d'isolation... quelque chose qui donne du sens au flux, en entrée ou en sortie du traitement (une source ou une destination), + /// - des décorateurs, + /// - des adaptateurs. + /// Tout ceci est représenté par la classe abstraite Stream, possédant un jeu de méthodes pour l'écriture, la lecture et le positionnement du curseur dans le flux. + /// Un Stream ne fonctionne pas comme un tableau ou une collection, ses données ne sont que partiellement accessible en fonction de l'avancement de la lecture ou de l'écriture. + /// En conséquence, le coût mémoire est plus faible, mais la navigation dans les données plus contrainte. + /// Reprenons les trois catégories : + /// - les backing stores streams peuvent être des sous-classes de Stream, comme : FileStream, NetworkStream, IsolatedStorageStream, MemoryStream. Cet exemple présentera FileStream. + /// - les décorateurs s'appuient sur les précédents et modifient leurs données, comme : DeflateStream, GZipStream, CryptoStream, BufferedStream. Les décorateurs ont la même interface Stream, + /// en conséquence, ils ne changent en rien l'utilisation du backing stores choisi. Ils le décorent et peuvent se chaîner ou se brancher à la volée. + /// Note : les backing stores et les décorateurs ne fonctionnent qu'avec des bytes. Pour les rendre plus "agréables" à manipuler, il faut utiliser des adaptateurs. + /// - les adaptateurs enveloppent les flux pour permettre de travailler avec du texte ou de l'XML et être ainsi plus proche de l'application. + /// Contrairement aux décorateurs, ils ne sont pas eux-mêmes des flux, et ne peuvent pas être chaînés. On compte parmi eux : StreamReader et StreamWriter pour le texte, + /// BinaryReader et BinaryWriter pour des données (int, float, string...), XmlReader et XmlWriter pour des données XML. + /// + /// La classe de base Stream fournit des méthodes pour lire (CanRead, Read, ReadByte), écrire (CanWrite, Write, WriteByte), chercher (CanSeek, Position, SetLength, Length, Seek), + /// fermer ou vider (Close, Dispose, Flush), configurer des timeouts (CanTimeout, ReadTimeout, WriteTimeout)... + /// Depuis la version 4.5 du .NET Framework, elle possède également des méthodes asynchrones de ces méthodes (ReadAsync, WriteAsync...). + /// + /// Dans la suite de cet exemple, nous utiliserons un FileStream. Puis dans les trois exemples suivants, nous utiliserons les adaptateurs StreamReader, StreamWriter, + /// BinaryReader, BinaryWriter, XmlReader, XmlWriter. + /// + /// + static void Main(string[] args) + { + OutputEncoding = Encoding.UTF8; + + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//..//ex_037_002_FileStream")); + //Construction d'un FileStream : le plus simple est d'utiliser l'un des trois méthodes suivantes + FileStream fileStream1 = File.OpenRead("fichier.txt"); // en lecture seule + fileStream1.Dispose(); + FileStream fileStream2 = File.OpenWrite("fichier2.txt"); // en écriture seule + fileStream2.Dispose(); + FileStream fileStream3 = File.Create("fichier3.txt"); // écriture et lecture + fileStream3.Dispose(); + + //on peut également instancier les FileStream de la manière suivante : + fileStream1 = new FileStream("fichier.txt", FileMode.Open); + fileStream1.Dispose(); + + //FileModes : + // - lecture seule : FileMode.Open + // - écriture/lecture : + // - si le fichier existe déjà : + // - FileMode.Truncate (tronque le fichier) + // - FileMode.Open : non tronqué + // - si le fichier n'existe pas : FileMode.CreateNew + // - si on ne sait pas... + // - FileMode.Create : tronque le fichier éventuellement existant + // - FileMode.OpenOrCreate : le laisse exister s'il existe déjà, sinon, le crée + // - FileMode.Append : pour ajouter à la fin du fichier + + + //on utilise en général un bloc using car un flux est une ressource non managée. + //le bloc using prend entre parenthèses la création du flux. A la fin du bloc, la ressource est automatiquement nettoyée (comme si on avait appelé Dispose). + //L'utilisation du bloc using part du principe qu'on se souvient toujours qu'il faudra nettoyer la mémoire non managée au moment où on la crée, mais que parfois, on oublie avant + // de le faire :) + // En conséquence, en même temps qu'on crée le flux, on dit qu'on le nettoye. + using (var fileStream4 = File.Create("fichier.txt")) + { + fileStream4.WriteByte(63); // écrit 63 + fileStream4.WriteByte(21); // écrit 21 + byte[] tab = { 1, 2, 3, 4, 5 }; + fileStream4.Write(tab, 0, tab.Length); // écrit un block de 5 bytes + + WriteLine($"taille actuelle du fileStream : {fileStream4.Length}"); // affiche la taille du fileStream + WriteLine($"position actuelle du fileStream : {fileStream4.Position}"); // affiche la position du fileStream + + fileStream4.Position = 0; // repositionne la position au début du fichier + + WriteLine(fileStream4.ReadByte()); // lit un byte (63) + WriteLine(fileStream4.ReadByte()); // lit un byte (21) + + byte[] tab2 = new byte[5]; + WriteLine(fileStream4.Read(tab2, 0, tab2.Length)); // lit un bloc de 5 bytes et les places dans tab + WriteLine(fileStream4.Read(tab2, 0, tab2.Length)); // comme nous sommes arrivés à la fin du fichier, la moindre lecture rend 0 + } + + //à peu près la même chose en asynchrone : + FileStreamExampleAsync(); + ReadLine(); + + //méthodes raccourcis qui font tout d'un seul coup + WriteLine(File.ReadAllText("exemple_filestream.txt")); + WriteLine(); + foreach (string line in File.ReadLines("exemple_filestream.txt")) + { + WriteLine($"-- {line}"); + } + + File.WriteAllText("exemple_filestream2.txt", File.ReadAllText("exemple_filestream.txt")); + File.WriteAllLines("exemple_filestream3.txt", File.ReadLines("exemple_filestream.txt").Select(s => $"-- {s}")); + } + + async static void FileStreamExampleAsync() + { + using (var fileStream5 = File.Create("fichier2.txt")) + { + byte[] tab = { 1, 2, 3, 4, 5 }; + await fileStream5.WriteAsync(tab, 0, tab.Length); // écrit un block de 5 bytes + + fileStream5.Position = 0; // repositionne la position au début du fichier + + byte[] tab2 = new byte[5]; + WriteLine(await fileStream5.ReadAsync(tab2, 0, tab2.Length)); // lit un bloc de 5 bytes et les places dans tab + } + } + } +} diff --git a/p07_Persistance/ex_037_002_FileStream/ex_037_002_FileStream.csproj b/p07_Persistance/ex_037_002_FileStream/ex_037_002_FileStream.csproj new file mode 100644 index 0000000..006feff --- /dev/null +++ b/p07_Persistance/ex_037_002_FileStream/ex_037_002_FileStream.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_037_002_FileStream + Exe + ex_037_002_FileStream + 6.0.6 + false + false + false + + diff --git a/p07_Persistance/ex_037_002_FileStream/exemple_filestream.txt b/p07_Persistance/ex_037_002_FileStream/exemple_filestream.txt new file mode 100644 index 0000000..12b7f3e --- /dev/null +++ b/p07_Persistance/ex_037_002_FileStream/exemple_filestream.txt @@ -0,0 +1,8 @@ +Attiré avant tout par le free jazz et le post-bop, Bobby Hutcherson a fait plusieurs enregistrements dans ces styles pour le label Blue Note avec Jackie McLean, Eric Dolphy, Andrew Hill, Grachan Moncur III, Joe Chambers, et Freddie Hubbard, comme leader ou comme sideman. +Malgré le grand nombre d'enregistrements d'avant-garde effectués durant cette période, la première session d'enregistrement de Hutcherson pour Blue Note, The Kicker (1963), laisse entrevoir son expérience du hard bop et du blues. +Beaucoup de ses enregistrements récents reviennent à ce hard bop et à un son moins aventureux. +En 1966, la session Stick-Up!, enregistrée chez Blue Note et faisant participer le saxophoniste Joe Henderson, est la première session que Bobby Hutcherson effectue avec le pianiste McCoy Tyner. +Leur collaboration se prolongera pendant plus de quatre décennies. +Little B's Poem (de son album Components) est l'une de ses compositions les plus connues. +En 2007, son quartette inclut Renee Rosnes au piano, Dwayne Bruno à la basse et Al Foster à la batterie. +Il meurt le 15 août 2016 après une longue lutte contre l'emphysème à l'âge de 75 ans. \ No newline at end of file diff --git a/p07_Persistance/ex_037_002_FileStream/fichier.txt b/p07_Persistance/ex_037_002_FileStream/fichier.txt new file mode 100644 index 0000000..2335890 --- /dev/null +++ b/p07_Persistance/ex_037_002_FileStream/fichier.txt @@ -0,0 +1 @@ +? \ No newline at end of file diff --git a/p07_Persistance/ex_037_003_TextReader_TextWriter/Program.cs b/p07_Persistance/ex_037_003_TextReader_TextWriter/Program.cs new file mode 100644 index 0000000..f7cd0de --- /dev/null +++ b/p07_Persistance/ex_037_003_TextReader_TextWriter/Program.cs @@ -0,0 +1,115 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// Mise à jour : 2017-09-18 +// +// ======================================================================== + +using System; +using System.IO; +using System.Text; +using static System.Console; + +namespace ex_037_003_TextReader_TextWriter +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = Encoding.UTF8; + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//..//ex_037_003_TextReader_TextWriter")); + + //METHODE 1 + //écriture de deux lignes dans un fichier + //using : on utilise un bloc using pour les ressources non managées (comme les streams, les images, etc...) + // using est un raccourci pour appeler Dispose() sur une instance d'un type implémentant IDisposable, + // tout en utilisant implicitement try/finally + // vous n'avez du coup pas besoin de nettoyer explicitement vos ressources si vous les construisez à l'intérieur d'un bloc using + + //construction d'un stream : celui-ci ne gère que des bytes + //si vous voulez écrire des char, des strings, des fragments xml, etc... vous devez brancher un adapter à votre stream + //ici, nous branchons un textwriter pour pouvoir écrire directement du texte + using (FileStream fs = File.Create("test1.txt")) + { + using (TextWriter writer = new StreamWriter(fs)) + { + writer.WriteLine("Une première ligne vraiment très intéressante..."); + writer.WriteLine("Une deuxième ligne vraiment très intéressante..."); + } + } + //lecture de deux lignes dans un fichier + using (FileStream fs = File.OpenRead("test1.txt")) + { + using (TextReader reader = new StreamReader(fs)) + { + WriteLine(reader.ReadLine()); + WriteLine(reader.ReadLine()); + } + } + + WriteLine("".PadRight(WindowWidth - 1, '*')); + + //METHODE 2 + //on branche tellement souvent un adapter de type Text à un stream, qu'il existe des raccourcis avec : + // File.CreateText, File.AppendText, File.OpenText + //Ceux-ci permettent de n'utiliser qu'un seul bloc using pour faire la même chose. + using (TextWriter writer = File.CreateText("test2.txt")) + { + writer.WriteLine("Une troisième ligne vraiment très intéressante..."); + writer.WriteLine("Une quatrième ligne vraiment très intéressante..."); + } + + //comme son nom l'indique, AppendText permet d'écrire à la fin du flux + using (TextWriter writer = File.AppendText("test2.txt")) + { + writer.WriteLine("Une cinquième ligne vraiment très intéressante..."); + } + + //Peek() permet de vérifier si on est arrivé à la fin du flux. + using (TextReader reader = File.OpenText("test2.txt")) + { + while (reader.Peek() > -1) + { + WriteLine(reader.ReadLine()); + } + } + + WriteLine("".PadRight(WindowWidth - 1, '*')); + + //on peut aussi tester si ReadLine rend null pour tester la fin du fichier + using (TextReader reader = File.OpenText("test2.txt")) + { + string line; + while ((line = reader.ReadLine()) != null) + { + WriteLine(line); + } + } + + WriteLine("".PadRight(WindowWidth - 1, '*')); + + //ECRIRE DES DONNEES AUTRES QUE DU TEXTE + using (TextWriter writer = File.CreateText("test3.txt")) + { + writer.WriteLine(12345); + writer.WriteLine(DateTime.Now); + writer.WriteLine(true); + } + + using (TextReader reader = File.OpenText("test3.txt")) + { + int.TryParse(reader.ReadLine(), out var a); + DateTime.TryParse(reader.ReadLine(), out var date); + bool.TryParse(reader.ReadLine(), out var b); + WriteLine(a); + WriteLine(date); + WriteLine(b); + } + } + } +} diff --git a/p07_Persistance/ex_037_003_TextReader_TextWriter/ex_037_003_TextReader_TextWriter.csproj b/p07_Persistance/ex_037_003_TextReader_TextWriter/ex_037_003_TextReader_TextWriter.csproj new file mode 100644 index 0000000..c909c24 --- /dev/null +++ b/p07_Persistance/ex_037_003_TextReader_TextWriter/ex_037_003_TextReader_TextWriter.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_037_003_TextReader_TextWriter + Exe + ex_037_003_TextReader_TextWriter + 6.0.6 + false + false + false + + diff --git a/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/Nounours.cs b/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/Nounours.cs new file mode 100644 index 0000000..9829688 --- /dev/null +++ b/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/Nounours.cs @@ -0,0 +1,91 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; + +namespace ex_037_004_BinaryReader_BinaryWriter +{ + public class Nounours + { + public string Nom + { + get; + set; + } + + public DateTime DateDeNaissance + { + get; + set; + } + + public int NbPoils + { + get; + set; + } + + public Nounours() + { + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/Program.cs b/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/Program.cs new file mode 100644 index 0000000..fbda569 --- /dev/null +++ b/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/Program.cs @@ -0,0 +1,64 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; +using System.IO; +using static System.Console; + +namespace ex_037_004_BinaryReader_BinaryWriter +{ + class Program + { + // BinaryReader et BinaryWriter lisent et écrivent des types natifs (bool, int, float, double, char, string...) + static void Main(string[] args) + { + Nounours nounours = new Nounours() + { + Nom = "Chewbacca", + DateDeNaissance = new DateTime(1977, 5, 27), + NbPoils = 1234567 + }; + WriteLine(nounours); + + SauvegarderNounours(nounours); + Nounours nounours2 = ChargerNounours(); + WriteLine(nounours2); + } + + static void SauvegarderNounours(Nounours nounours) + { + using (FileStream fs = File.Create("nounours.txt")) + { + BinaryWriter writer = new BinaryWriter(fs); + writer.Write(nounours.Nom); + writer.Write(nounours.DateDeNaissance.ToString()); + writer.Write(nounours.NbPoils); + writer.Flush(); + } + } + + static Nounours ChargerNounours() + { + Nounours nounours; + using (FileStream fs = File.OpenRead("nounours.txt")) + { + BinaryReader reader = new BinaryReader(fs); + nounours = new Nounours() + { + Nom = reader.ReadString(), + DateDeNaissance = DateTime.Parse(reader.ReadString()), + NbPoils = reader.ReadInt32() + }; + } + return nounours; + } + } +} diff --git a/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/ex_037_004_BinaryReader_BinaryWriter.csproj b/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/ex_037_004_BinaryReader_BinaryWriter.csproj new file mode 100644 index 0000000..8bcbf49 --- /dev/null +++ b/p07_Persistance/ex_037_004_BinaryReader_BinaryWriter/ex_037_004_BinaryReader_BinaryWriter.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_037_004_BinaryReader_BinaryWriter + Exe + ex_037_004_BinaryReader_BinaryWriter + 6.0.6 + false + false + false + + diff --git a/p07_Persistance/ex_037_005_XmlReader_XmlWriter/Nounours.cs b/p07_Persistance/ex_037_005_XmlReader_XmlWriter/Nounours.cs new file mode 100644 index 0000000..8b0431a --- /dev/null +++ b/p07_Persistance/ex_037_005_XmlReader_XmlWriter/Nounours.cs @@ -0,0 +1,91 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; + +namespace ex_037_005_XmlReader_XmlWriter +{ + public class Nounours + { + public string Nom + { + get; + set; + } + + public DateTime DateDeNaissance + { + get; + set; + } + + public int NbPoils + { + get; + set; + } + + public Nounours() + { + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_037_005_XmlReader_XmlWriter/Program.cs b/p07_Persistance/ex_037_005_XmlReader_XmlWriter/Program.cs new file mode 100644 index 0000000..a05678a --- /dev/null +++ b/p07_Persistance/ex_037_005_XmlReader_XmlWriter/Program.cs @@ -0,0 +1,103 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-04 +// +// ======================================================================== + +using System; +using System.IO; +using System.Text; +using System.Xml; +using static System.Console; + +namespace ex_037_005_XmlReader_XmlWriter +{ + class Program + { + // XmlReader et XmlWriter lisent et écrivent des fragments XML + static void Main(string[] args) + { + OutputEncoding = Encoding.UTF8; + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//..//ex_037_005_XmlReader_XmlWriter", "XML")); + + Nounours nounours = new Nounours() + { + Nom = "Chewbacca", + DateDeNaissance = new DateTime(1977, 5, 27), + NbPoils = 1234567 + }; + WriteLine(nounours); + + SauvegarderNounours(nounours); + Nounours nounours2 = ChargerNounours(); + WriteLine(nounours2); + } + + static void SauvegarderNounours(Nounours nounours) + { + string xmlFile = "nounours.xml"; + + //settings pour que le fichier écrit soit indenté + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + + //création du writer + using (TextWriter tw = File.CreateText(xmlFile)) + { + using (XmlWriter mWriter = XmlWriter.Create(tw, settings)) + { + + //écrit l'élément racine "nounours" + mWriter.WriteStartElement("nounours"); + + //écrit l'attribut @nom + mWriter.WriteAttributeString("nom", nounours.Nom); + + //écrit le sous-élément naissance + mWriter.WriteStartElement("naissance"); + mWriter.WriteValue(nounours.DateDeNaissance); + mWriter.WriteEndElement(); + + //écrit le sous-élément nb_poils + mWriter.WriteStartElement("nb_poils"); + mWriter.WriteValue(nounours.NbPoils); + mWriter.WriteEndElement(); + + //ferme la balise nounours + mWriter.WriteEndElement(); + } + } + } + + static Nounours ChargerNounours() + { + string xmlFile = "nounours.xml"; + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreWhitespace = true; + settings.IgnoreComments = true; + settings.IgnoreProcessingInstructions = true; + + XmlReader reader = XmlReader.Create(xmlFile, settings); + + Nounours nounours = new Nounours(); + + while (reader.NodeType != XmlNodeType.Element) + { + reader.Read(); + } + nounours.Nom = reader.GetAttribute("nom"); + reader.ReadStartElement("nounours"); + nounours.DateDeNaissance = XmlConvert.ToDateTime(reader.ReadElementContentAsString("naissance", ""), XmlDateTimeSerializationMode.Utc); + nounours.NbPoils = reader.ReadElementContentAsInt("nb_poils", ""); + reader.ReadEndElement(); + + return nounours; + } + } +} diff --git a/p07_Persistance/ex_037_005_XmlReader_XmlWriter/XML/nounours.xml b/p07_Persistance/ex_037_005_XmlReader_XmlWriter/XML/nounours.xml new file mode 100644 index 0000000..338937e --- /dev/null +++ b/p07_Persistance/ex_037_005_XmlReader_XmlWriter/XML/nounours.xml @@ -0,0 +1,5 @@ + + + 1977-05-27T00:00:00 + 1234567 + \ No newline at end of file diff --git a/p07_Persistance/ex_037_005_XmlReader_XmlWriter/ex_037_005_XmlReader_XmlWriter.csproj b/p07_Persistance/ex_037_005_XmlReader_XmlWriter/ex_037_005_XmlReader_XmlWriter.csproj new file mode 100644 index 0000000..466363e --- /dev/null +++ b/p07_Persistance/ex_037_005_XmlReader_XmlWriter/ex_037_005_XmlReader_XmlWriter.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_037_005_XmlReader_XmlWriter + Exe + ex_037_005_XmlReader_XmlWriter + 6.0.6 + false + false + false + + diff --git a/p07_Persistance/ex_038_001_DataContractSerializer_bases/Nounours.cs b/p07_Persistance/ex_038_001_DataContractSerializer_bases/Nounours.cs new file mode 100644 index 0000000..4165c0b --- /dev/null +++ b/p07_Persistance/ex_038_001_DataContractSerializer_bases/Nounours.cs @@ -0,0 +1,136 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-05 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace ex_038_001_DataContractSerializer_bases +{ + /// + /// Pour que Nounours soit sérialisable/désérialisable avec DataContractSerializer, il faut décorer le type et ses membres à sérialiser avec des attributs + /// 1) pour cela, il faut ajouter [DataContract] à la définition du type comme ci-dessous. + /// Vous pouvez lui rajouter trois paramètres optionnels : + /// - IsReference qui indique s'il faut conserver les données de références objets + /// - Name permet de définir le texte qui sera utilisé dans la balise XML (par défaut, le nom du type) + /// - Namespace permet de définir l'espace de noms utilisé (par défaut, aucun) + /// 2) il faut ensuite ajouter [DataMember] devant la définition de chaque propriété à sérialiser + /// Vous pouvez également rajouter des paramètres optionnels : + /// - EmitDefaultValue indique si il faut quand même sérialiser la propriété si sa valeur est celle par défaut (null par exemple pour un type référence) + /// - IsRequired indique si l'élément correspondant à cette propriété doit être obligatoirement présent ou non + /// - Name + /// - Order indique si l'élément doit toujours avoir la même position dans les sous-éléments du type + /// + /// Note : [DataMember] peut être attaché aux propriétés dont le type est : + /// - un type primitif + /// - un DateTime, TimeSpan, Guid, Uri, un enum + /// - NullableType d'un des types précédents + /// - un byte[] (sérialisé en XML au format base64) + /// - n'importe quel type personnalisé décoré par [DataContract] + /// - n'importe quelle collection (si les éléments de la collection vérifient la condition précédente) + /// - n'importe quel type décoré avec [Serializable] + /// - n'importe quel type implémentant IXmlSerializable + + /// + [DataContract(Name = "nounours")] + public class Nounours + { + [DataMember] + public string Nom + { + get; + set; + } + + [DataMember(Name = "naissance")] + public DateTime DateDeNaissance + { + get; + set; + } + + [DataMember] + public int NbPoils + { + get; + set; + } + + [DataMember(EmitDefaultValue = false)] + public List Amis + { + get; + set; + } + + public Nounours() + { + Amis = new List(); + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + string amisStr = String.Empty; + if (Amis.Count > 0) + { + amisStr = $", amis : {Amis.Select(nounours => nounours.Nom).Aggregate((noms, nom) => $"{noms} {nom}")}"; + } + return $"{Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils{amisStr})"; + } + + } +} diff --git a/p07_Persistance/ex_038_001_DataContractSerializer_bases/Program.cs b/p07_Persistance/ex_038_001_DataContractSerializer_bases/Program.cs new file mode 100644 index 0000000..01efa7d --- /dev/null +++ b/p07_Persistance/ex_038_001_DataContractSerializer_bases/Program.cs @@ -0,0 +1,141 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-05 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.Xml; +using static System.Console; + +namespace ex_038_001_DataContractSerializer_bases +{ + class Program + { + static void Main(string[] args) + { + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + string xmlFile = "nounours.xml"; + + Nounours chewie = new Nounours() + { + Nom = "Chewbacca", + DateDeNaissance = new DateTime(1977, 5, 27), + NbPoils = 1234567 + }; + + Nounours yoda = new Nounours() + { + Nom = "Yoda", + DateDeNaissance = new DateTime(1980, 5, 21), + NbPoils = 3 + }; + + Nounours ewok = new Nounours() + { + Nom = "Ewok", + DateDeNaissance = new DateTime(1983, 5, 25), + NbPoils = 3456789 + }; + + chewie.Amis.Add(yoda); + chewie.Amis.Add(ewok); + + WriteLine(chewie); + + + //ATTENTION : pour que le DataContractSerializer fonctionne, vous devez avoir décoré l'objet à sérialiser ! + //cf. Nounours.cs + + + //1. Sérialisation d'un chewie en xml avec la méthode par défaut + //- on construit le sérialiseur en précisant le type de l'objet à sérialiser + //- on crée le flux (de préférence avec using pour ne pas oublier d'appeler Dispose à la fin) en écriture + //- on appelle WriteObject pour sérialiser + var serializer = new DataContractSerializer(typeof(Nounours)); + + using (Stream s = File.Create(xmlFile)) + { + serializer.WriteObject(s, chewie); + } + + //- pour désérialiser, on crée le flux (de préférence avec using) en lecture + //- on appelle ReadObject + Nounours nounours2; + using (Stream s = File.OpenRead(xmlFile)) + { + nounours2 = serializer.ReadObject(s) as Nounours; + } + + WriteLine(nounours2); + + + + + + //2. spécifier le XmlWriter pour que cela soit plus lisible (indentation) + //- même chose qu'avant, mais en utilisant un XmlWriter, on peut ajouter des settings, notamment pour l'indentation et le rendre plus lisible + string xmlFile2 = "nounours2.xml"; + + XmlWriterSettings settings = new XmlWriterSettings() { Indent = true }; + using (TextWriter tw = File.CreateText(xmlFile2)) + { + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer.WriteObject(writer, chewie); + } + } + + + + + // Par défaut, le formatage est XML, mais vous pouvez spécifier un formatage binaire. + //3. Formatage binaire + using (FileStream stream = File.Create("nounours.txt")) + { + using (XmlDictionaryWriter xmlDicoWriter = XmlDictionaryWriter.CreateBinaryWriter(stream)) + { + serializer.WriteObject(xmlDicoWriter, chewie); + } + } + + Nounours nounours3; + using (FileStream stream2 = File.OpenRead("nounours.txt")) + { + using (XmlDictionaryReader xmlDicoReader = XmlDictionaryReader.CreateBinaryReader(stream2, XmlDictionaryReaderQuotas.Max)) + { + nounours3 = serializer.ReadObject(xmlDicoReader) as Nounours; + } + } + WriteLine(nounours3); + + //... ou Json avec un DataContractJsonSerializer + //4. Formatage Json + DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Nounours)); + MemoryStream memoryStream = new MemoryStream(); + jsonSerializer.WriteObject(memoryStream, chewie); + using (FileStream stream = File.Create("nounours.json")) + { + memoryStream.WriteTo(stream); + } + + Nounours nounours4; + using (FileStream stream2 = File.OpenRead("nounours.json")) + { + nounours4 = jsonSerializer.ReadObject(stream2) as Nounours; + } + WriteLine(nounours4); + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_038_001_DataContractSerializer_bases/XML/.gitignore b/p07_Persistance/ex_038_001_DataContractSerializer_bases/XML/.gitignore new file mode 100644 index 0000000..250c9bc --- /dev/null +++ b/p07_Persistance/ex_038_001_DataContractSerializer_bases/XML/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory + +# Except this file +!.gitignore \ No newline at end of file diff --git a/p07_Persistance/ex_038_001_DataContractSerializer_bases/ex_038_001_DataContractSerializer_bases.csproj b/p07_Persistance/ex_038_001_DataContractSerializer_bases/ex_038_001_DataContractSerializer_bases.csproj new file mode 100644 index 0000000..4f94043 --- /dev/null +++ b/p07_Persistance/ex_038_001_DataContractSerializer_bases/ex_038_001_DataContractSerializer_bases.csproj @@ -0,0 +1,16 @@ + + + net6.0 + ex_038_001_DataContractSerializer_bases + Exe + ex_038_001_DataContractSerializer_bases + 6.0.6 + false + false + false + + + + + + diff --git a/p07_Persistance/ex_038_002_DataContract_subclassing/Animal.cs b/p07_Persistance/ex_038_002_DataContract_subclassing/Animal.cs new file mode 100644 index 0000000..991278f --- /dev/null +++ b/p07_Persistance/ex_038_002_DataContract_subclassing/Animal.cs @@ -0,0 +1,39 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Animal.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-05 +// +// ======================================================================== + +using System.Runtime.Serialization; + +namespace ex_038_002_DataContract_subclassing +{ + [DataContract, KnownType(typeof(Chat)), KnownType(typeof(Chien))] + class Animal + { + [DataMember] + public string Nom + { + get; + set; + } + + [DataMember] + public string Bruit + { + get; + set; + } + + public Animal(string nom, string bruit) + { + Nom = nom; + Bruit = bruit; + } + } +} diff --git a/p07_Persistance/ex_038_002_DataContract_subclassing/Chat.cs b/p07_Persistance/ex_038_002_DataContract_subclassing/Chat.cs new file mode 100644 index 0000000..61dc323 --- /dev/null +++ b/p07_Persistance/ex_038_002_DataContract_subclassing/Chat.cs @@ -0,0 +1,32 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chat.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-05 +// +// ======================================================================== + +using System; +using System.Runtime.Serialization; + +namespace ex_038_002_DataContract_subclassing +{ + [DataContract] + class Chat : Animal + { + [DataMember] + public TimeSpan DuréeSieste + { + get; + set; + } + + public Chat(string name, TimeSpan duréeSieste) : base(name, "Miaou") + { + DuréeSieste = duréeSieste; + } + } +} diff --git a/p07_Persistance/ex_038_002_DataContract_subclassing/Chien.cs b/p07_Persistance/ex_038_002_DataContract_subclassing/Chien.cs new file mode 100644 index 0000000..d787fca --- /dev/null +++ b/p07_Persistance/ex_038_002_DataContract_subclassing/Chien.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chien.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-05 +// +// ======================================================================== + +using System.Runtime.Serialization; + +namespace ex_038_002_DataContract_subclassing +{ + [DataContract] + class Chien : Animal + { + [DataMember] + public int NbOsRongés + { + get; + set; + } + + public Chien(string name, int nbOsRongés) : base(name, "Wouf Wouf") + { + NbOsRongés = nbOsRongés; + } + } +} diff --git a/p07_Persistance/ex_038_002_DataContract_subclassing/Oiseau.cs b/p07_Persistance/ex_038_002_DataContract_subclassing/Oiseau.cs new file mode 100644 index 0000000..fab6c1e --- /dev/null +++ b/p07_Persistance/ex_038_002_DataContract_subclassing/Oiseau.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Oiseau.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-05 +// +// ======================================================================== + +using System; +using System.Runtime.Serialization; + +namespace ex_038_002_DataContract_subclassing +{ + [DataContract] + class Oiseau : Animal + { + [DataMember] + public TimeSpan TempsDeVol + { + get; set; + } + + public Oiseau(string nom, TimeSpan tempsDeVol) : base(nom, "Cui Cui") + { + TempsDeVol = tempsDeVol; + } + } +} diff --git a/p07_Persistance/ex_038_002_DataContract_subclassing/Program.cs b/p07_Persistance/ex_038_002_DataContract_subclassing/Program.cs new file mode 100644 index 0000000..2c72520 --- /dev/null +++ b/p07_Persistance/ex_038_002_DataContract_subclassing/Program.cs @@ -0,0 +1,128 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-05 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Xml; +using static System.Console; + +namespace ex_038_002_DataContract_subclassing +{ + class Program + { + /// + /// Dans le Framework .NET, il était nécessaire de préciser le type des classes filles avec l'une des deux méthodes présentées dans l'exemple suivant. + /// Néanmoins, en .NET Core, cela ne semble plus nécessaire. Si on ne déclare pas les classes filles dans les sérialiseur, il s'en sort quand même ! + /// Voici néanmoins les explications. + /// + /// Dans l'exemple suivant, trois classes (Chat, Chien et Oiseau) dérivent de la classe Animal. Animal, Chat et Chien sont décorées avec DataContract et DataMember. + /// Nous avons trois variables de type Animal, mais l'une a été construite avec le constructeur d'Animal, la 2ème avec celui de Chat, et la 3ème avec celui de Chien. + /// Nous sérialisons les trois variables de type Animal, et pourtant le sérialiseur sérialise un Animal, un Chat et un Chien. + /// + /// Pour que cela soit possible, il faut utiliser l'une des deux solutions suivantes : + /// 1- dans la classe mère, on augmente l'attribut DataContract avec KnownType et on précise quelles sont les classes filles. + /// Par exemple, ici on a : [DataContract, KnownType(typeof(Chat)), KnownType(typeof(Chien))] class Animal { ... } (cf. Animal.cs) + /// 2- dans la construction du sérialiseur, on donne les types fils qu'on peut avoir à sérialiser. Ceci est indispensable, si on ne connait pas à l'avance les classes filles + /// au moment de l'écriture de la classe mère. + /// + /// Comme expliqué ci-dessus, en .NET Core, il n'est plus nécessaire d'effectuer l'une des deux opérations précédentes. + /// + /// + static void Main(string[] args) + { + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + + Animal jojo = new Animal("jojo", "pfffff"); + Animal grosminet = new Chat("Grosminet", TimeSpan.FromHours(4.0)); + Animal idefix = new Chien("Idefix", 5); + Animal titi = new Oiseau("Titi", TimeSpan.FromHours(12.0)); + + //1- sérialiseur sans préciser quels sont les types fils + //(en conséquence, seuls ceux qui sont déclarés en KnownType dans l'attribut DataContract de la classe mère sont reconnus + var serializer = new DataContractSerializer(typeof(Animal)); + + XmlWriterSettings settings = new XmlWriterSettings() { Indent = true }; + using (TextWriter tw = File.CreateText("animal.xml")) + { + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer.WriteObject(writer, jojo); + } + } + + using (TextWriter tw = File.CreateText("chat.xml")) + { + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer.WriteObject(writer, grosminet); + } + } + + using (TextWriter tw = File.CreateText("chien.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer.WriteObject(writer, idefix); + } + + //le type Oiseau n'est pas sérialisé + try + { + using (TextWriter tw = File.CreateText("oiseau.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer.WriteObject(writer, titi); + } + } + catch (Exception exc) + { + WriteLine(exc); + } + + + //2- on précise au sérialiseur qu'il peut tomber sur un type Oiseau + var serializer2 = new DataContractSerializer(typeof(Animal), new Type[] { typeof(Oiseau) }); + using (TextWriter tw = File.CreateText("animal2.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer2.WriteObject(writer, jojo); + } + + using (TextWriter tw = File.CreateText("chat2.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer2.WriteObject(writer, grosminet); + } + + using (TextWriter tw = File.CreateText("chien2.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer2.WriteObject(writer, idefix); + } + + try + { + using (TextWriter tw = File.CreateText("oiseau2.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer2.WriteObject(writer, titi); + } + } + catch (Exception exc) + { + WriteLine(exc); + } + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_038_002_DataContract_subclassing/XML/.gitignore b/p07_Persistance/ex_038_002_DataContract_subclassing/XML/.gitignore new file mode 100644 index 0000000..250c9bc --- /dev/null +++ b/p07_Persistance/ex_038_002_DataContract_subclassing/XML/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory + +# Except this file +!.gitignore \ No newline at end of file diff --git a/p07_Persistance/ex_038_002_DataContract_subclassing/ex_038_002_DataContract_subclassing.csproj b/p07_Persistance/ex_038_002_DataContract_subclassing/ex_038_002_DataContract_subclassing.csproj new file mode 100644 index 0000000..75d7fc4 --- /dev/null +++ b/p07_Persistance/ex_038_002_DataContract_subclassing/ex_038_002_DataContract_subclassing.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_038_002_DataContract_subclassing + Exe + ex_038_002_DataContract_subclassing + 6.0.6 + false + false + false + + + + + diff --git a/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Album.cs b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Album.cs new file mode 100644 index 0000000..87ec767 --- /dev/null +++ b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Album.cs @@ -0,0 +1,47 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Album.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-06 +// +// ======================================================================== + +using System.Runtime.Serialization; + +namespace ex_038_003_DataContract_ObjectReferences +{ + /// + /// Album est sérialisable en utilisant DataContractSerializer + /// Il possède deux références vers des artistes (pas de collection pour le moment, ce sera traité dans l'exemple suivant). + /// + [DataContract] + class Album + { + [DataMember(Order = 1)] + public string Titre + { + get; set; + } + + [DataMember(Order = 3)] + public Artiste Artiste1 + { + get; set; + } + + [DataMember(Order = 4)] + public Artiste Artiste2 + { + get; set; + } + + [DataMember(Order = 2)] + public int AnnéeDeSortie + { + get; set; + } + } +} diff --git a/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Artiste.cs b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Artiste.cs new file mode 100644 index 0000000..d749605 --- /dev/null +++ b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Artiste.cs @@ -0,0 +1,47 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Artiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-06 +// +// ======================================================================== + +using System; +using System.Runtime.Serialization; + +namespace ex_038_003_DataContract_ObjectReferences +{ + /// + /// Artiste est sérialisable en utilisant DataContractSerializer. + /// + [DataContract] + class Artiste + { + [DataMember(Order = 1)] + public string Prénom + { + get; set; + } + + [DataMember(Order = 2)] + public string Nom + { + get; set; + } + + [DataMember(Order = 3)] + public DateTime Naissance + { + get; set; + } + + [DataMember(Order = 4)] + public string Instrument + { + get; set; + } + } +} diff --git a/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Morceau.cs b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Morceau.cs new file mode 100644 index 0000000..de2aff8 --- /dev/null +++ b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Morceau.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Morceau.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-06 +// +// ======================================================================== + +using System.Runtime.Serialization; + +namespace ex_038_003_DataContract_ObjectReferences +{ + /// + /// Morceau est sérialisable en utilisant DataContractSerializer. + /// Il possède une référence vers un Artiste (le compositeur) et un Album (qui contient ce morceau). + /// + [DataContract] + class Morceau + { + [DataMember(Order = 1)] + public string Titre + { + get; set; + } + + [DataMember(Order = 2)] + public Artiste Compositeur + { + get; set; + } + + [DataMember(Order = 3)] + public Album Album + { + get; set; + } + } +} diff --git a/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Program.cs b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Program.cs new file mode 100644 index 0000000..877145a --- /dev/null +++ b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/Program.cs @@ -0,0 +1,90 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-06 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Xml; +using static System.Console; + +namespace ex_038_003_DataContract_ObjectReferences +{ + class Program + { + static void Main(string[] args) + { + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + + //on crée la structure suivante : + //Morceau(bulgarska) --compositeur--> Artiste(Bojan Z) + // --album--------> Album (Duo) --Artiste1--> Artiste(BojanZ) + // --Artiste2--> Artiste(Julien Lourau) + //On va persister Morceau. On voit donc ici que la sérialisation de Morceau va entrainer la sérialisation d'un artiste (le compositeur), + // et d'un Album qui va entrainer la sérialisation de deux artistes (Bojan Z et Julien Lourau). + //L'Artiste Bojan Z va donc être sérialisé deux fois dans le même fichier. C'est ce qu'on veut éviter. + // + //Dans la 1ère partie de l'exemple, la sérialisation ne gère pas les références d'objets. + //Cela sera fait dans la 2ème partie. + + //création des instances d'Artiste, Album et Morceau + Artiste bojan = new Artiste { Prénom = "Bojan", Nom = "Z", Naissance = new DateTime(1968, 2, 2), Instrument = "Piano" }; + Artiste julien = new Artiste { Prénom = "Julien", Nom = "Lourau", Naissance = new DateTime(1970, 1, 1), Instrument = "Saxophone" }; + + Album duo = new Album { Titre = "Duo", AnnéeDeSortie = 2015, Artiste1 = bojan, Artiste2 = julien }; + + Morceau bulgarska = new Morceau { Titre = "Bulgarska", Album = duo, Compositeur = bojan }; + + //--1-- pas de gestion des références d'objets + //création du sérialiseur en n'indiquant que le type d'objet à sérialiser (ici Morceau) + var serializer = new DataContractSerializer(typeof(Morceau)); + + //sérialisation + XmlWriterSettings settings = new XmlWriterSettings() { Indent = true }; + using (TextWriter tw = File.CreateText("bulgarska.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer.WriteObject(writer, bulgarska); + } + //observez le fichier bulgarska.xml pour constater que l'Artiste Bojan Z est sérialisé deux fois. + // on voit notamment deux fois le fragment XML suivant : + // Bojan + // Z + // 1968-02-02T00:00:00 + // Piano + + + //--2-- gestion des références d'objets + //création du sérialiseur + //dans cette version du constructeur, on peut spécifier dans les settings du serializer qu'on veut gérer les références d'objets. + var serializer2 = new DataContractSerializer(typeof(Morceau), new DataContractSerializerSettings() { PreserveObjectReferences=true }); + + //sérialisation + using (TextWriter tw = File.CreateText("bulgarska2.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer2.WriteObject(writer, bulgarska); + } + //observez le fichier bulgarska2.xml pour constater que l'Artiste Bojan Z n'est sérialisé qu'une fois et qu'on y fait référence par la suite : + //Forme de la sérialisation (notez la présence des z:Id): + // + // Bojan + // Z + // 1968-02-02T00:00:00 + // Piano + // + //La deuxième fois que l'Artiste aurait dû être sérialisé, il n'y est que fait référence (notez la présence de z:Ref) : + // + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_038_003_DataContract_ObjectReferences/XML/.gitignore b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/XML/.gitignore new file mode 100644 index 0000000..250c9bc --- /dev/null +++ b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/XML/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory + +# Except this file +!.gitignore \ No newline at end of file diff --git a/p07_Persistance/ex_038_003_DataContract_ObjectReferences/ex_038_003_DataContract_ObjectReferences.csproj b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/ex_038_003_DataContract_ObjectReferences.csproj new file mode 100644 index 0000000..2c6185c --- /dev/null +++ b/p07_Persistance/ex_038_003_DataContract_ObjectReferences/ex_038_003_DataContract_ObjectReferences.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_038_003_DataContract_ObjectReferences + Exe + ex_038_003_DataContract_ObjectReferences + 6.0.6 + false + false + false + + + + + diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/Animal.cs b/p07_Persistance/ex_038_004_DataContract_Collections/Animal.cs new file mode 100644 index 0000000..3cd4ab7 --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/Animal.cs @@ -0,0 +1,39 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Animal.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System.Runtime.Serialization; + +namespace ex_038_004_DataContract_Collections +{ + [DataContract, KnownType(typeof(Chat)), KnownType(typeof(Chien))] + class Animal + { + [DataMember] + public string Nom + { + get; + set; + } + + [DataMember] + public string Bruit + { + get; + set; + } + + public Animal(string nom, string bruit) + { + Nom = nom; + Bruit = bruit; + } + } +} diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/AnimalList.cs b/p07_Persistance/ex_038_004_DataContract_Collections/AnimalList.cs new file mode 100644 index 0000000..f906395 --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/AnimalList.cs @@ -0,0 +1,33 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AnimalList.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace ex_038_004_DataContract_Collections +{ + /// + /// AnimalList est une classe qui dérive d'une collection. + /// On n'utilise pas ici un attribut [DataContract] mais [CollectionDataContract] + /// Celui-ci nous permet de plus d'indiquer un nom de balise différent pour les items de la collection (ici unAnimal). + /// + [CollectionDataContract(ItemName = "unAnimal")] + class AnimalList : List + { + public AnimalList() + { + Add(new Chat("GrosMinet", TimeSpan.FromHours(3))); + Add(new Oiseau("Titi", TimeSpan.FromHours(1))); + Add(new Chien("Idefix", 50)); + } + } +} diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/Chat.cs b/p07_Persistance/ex_038_004_DataContract_Collections/Chat.cs new file mode 100644 index 0000000..daae5dd --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/Chat.cs @@ -0,0 +1,32 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chat.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System; +using System.Runtime.Serialization; + +namespace ex_038_004_DataContract_Collections +{ + [DataContract] + class Chat : Animal + { + [DataMember] + public TimeSpan DuréeSieste + { + get; + set; + } + + public Chat(string name, TimeSpan duréeSieste) : base(name, "Miaou") + { + DuréeSieste = duréeSieste; + } + } +} diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/Chien.cs b/p07_Persistance/ex_038_004_DataContract_Collections/Chien.cs new file mode 100644 index 0000000..503cf25 --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/Chien.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chien.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System.Runtime.Serialization; + +namespace ex_038_004_DataContract_Collections +{ + [DataContract] + class Chien : Animal + { + [DataMember] + public int NbOsRongés + { + get; + set; + } + + public Chien(string name, int nbOsRongés) : base(name, "Wouf Wouf") + { + NbOsRongés = nbOsRongés; + } + } +} diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/Ménagerie.cs b/p07_Persistance/ex_038_004_DataContract_Collections/Ménagerie.cs new file mode 100644 index 0000000..ec01920 --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/Ménagerie.cs @@ -0,0 +1,53 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Ménagerie.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace ex_038_004_DataContract_Collections +{ + /// + /// Ménagerie contient deux collections : une de Chat et une de Animal. + /// Ces collections sont privées (List et List) + /// et encapsulées en lecture seule par des propriétés de type IEnumerable générique. + /// Notez que le [DataMember] est placé devant le membre et pas devant la propriété pour une fois. Pourquoi ? + /// Lors de la désérialisation, le désérialiseur en voyant un type abstrait, ne saura pas quel type utiliser. + /// Par conséquent, il va créer des tableaux (Chat[] et Animal[]) ce qui ne pourra pas convenir pour notre classe. + /// Dès lors, on préfère placer dans ce cas le [DataMember] devant les membres privés. + /// + /// Notez également qu'une collection d'un type père se sérialise parfaitement en sérialisant les items de types fils. + /// + [DataContract] + class Ménagerie + { + [DataMember(Order = 0)] + public string Nom { get; set; } + + public IEnumerable Chats => chats; + + [DataMember(Name = "Chats", Order = 1)] + private List chats = new List { + new Chat("Isidore", TimeSpan.FromHours(4)), + new Chat("Garfield", TimeSpan.FromHours(12)), + new Chat("GrosMinet", TimeSpan.FromHours(3))}; + + public IEnumerable Animaux => animaux; + + [DataMember(Name = "Animaux", Order = 2)] + private List animaux = new List + { + new Chat("GrosMinet", TimeSpan.FromHours(3)), + new Oiseau("Titi", TimeSpan.FromHours(1)), + new Chien("Idefix", 50) + }; + } +} diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/Oiseau.cs b/p07_Persistance/ex_038_004_DataContract_Collections/Oiseau.cs new file mode 100644 index 0000000..10fc3ae --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/Oiseau.cs @@ -0,0 +1,31 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Oiseau.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System; +using System.Runtime.Serialization; + +namespace ex_038_004_DataContract_Collections +{ + [DataContract] + class Oiseau : Animal + { + [DataMember] + public TimeSpan TempsDeVol + { + get; set; + } + + public Oiseau(string nom, TimeSpan tempsDeVol) : base(nom, "Cui Cui") + { + TempsDeVol = tempsDeVol; + } + } +} diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/Program.cs b/p07_Persistance/ex_038_004_DataContract_Collections/Program.cs new file mode 100644 index 0000000..6c715f4 --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/Program.cs @@ -0,0 +1,89 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Xml; +using static System.Console; + +namespace ex_038_004_DataContract_Collections +{ + class Program + { + /// + /// le DataContractSerializer peut sérialiser et désérialiser n'importe quel type de collections. + /// Voici quelques exemples : + /// + /// + static void Main(string[] args) + { + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + + List animaux = new List + { + new Chat("GrosMinet", TimeSpan.FromHours(3)), + new Oiseau("Titi", TimeSpan.FromHours(1)), + new Chien("Idefix", 50) + }; + + // ===1=== + //on sérialise ici une collection d'Animal. Il suffit juste de donner le type de l'élément à sérialiser au sérialiseur, i.e. ici List + //Comme Animal connait les types Chat et Chien, pas besoin de les donner au sérialiseur. + //Puisque Animal ne connait pas le type Oiseau, il faut préciser au sérialiseur qu'il peut tomber dessus. + var serializerListAnimal = new DataContractSerializer(typeof(List), new Type[] { typeof(Oiseau) }); + + //sérialisation + XmlWriterSettings settings = new XmlWriterSettings() { Indent = true }; + using (TextWriter tw = File.CreateText("List_Animal.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializerListAnimal.WriteObject(writer, animaux); + } + + + // ===2=== + //Ici, on va sérialiser une classe Ménagerie qui contient deux collections : une de Chat et une de Animal + //Notez encore une fois qu'on précise au sérialiseur qu'il peut tomber sur des Oiseau + //Lisez les commentaires dans Ménagerie pour plus d'explications. + Ménagerie ménagerie = new Ménagerie { Nom = "mon Zoo" }; + + var serializerMénagerie = new DataContractSerializer(typeof(Ménagerie), new Type[] { typeof(Oiseau) }); + + //sérialisation + using (TextWriter tw = File.CreateText("Ménagerie.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializerMénagerie.WriteObject(writer, ménagerie); + } + + + // ===3=== + //Enfin, AnimalList est une classe qui dérive d'une collection. + //Elle utilise un attribut légèrement différent. + //Lisez les commentaires de AnimalList pour le découvrir. + AnimalList animalList = new AnimalList(); + + var serializerAnimalList = new DataContractSerializer(typeof(AnimalList), new Type[] { typeof(Oiseau) }); + + //sérialisation + using (TextWriter tw = File.CreateText("AnimalList.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializerAnimalList.WriteObject(writer, animalList); + } + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/XML/.gitignore b/p07_Persistance/ex_038_004_DataContract_Collections/XML/.gitignore new file mode 100644 index 0000000..250c9bc --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/XML/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory + +# Except this file +!.gitignore \ No newline at end of file diff --git a/p07_Persistance/ex_038_004_DataContract_Collections/ex_038_004_DataContract_Collections.csproj b/p07_Persistance/ex_038_004_DataContract_Collections/ex_038_004_DataContract_Collections.csproj new file mode 100644 index 0000000..0b1614b --- /dev/null +++ b/p07_Persistance/ex_038_004_DataContract_Collections/ex_038_004_DataContract_Collections.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_038_004_DataContract_Collections + Exe + ex_038_004_DataContract_Collections + 6.0.6 + false + false + false + + + + + diff --git a/p07_Persistance/ex_038_005_DataContract_Hooks/Animal.cs b/p07_Persistance/ex_038_005_DataContract_Hooks/Animal.cs new file mode 100644 index 0000000..f1eb4b5 --- /dev/null +++ b/p07_Persistance/ex_038_005_DataContract_Hooks/Animal.cs @@ -0,0 +1,53 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Animal.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System.Runtime.Serialization; + +namespace ex_038_004_DataContract_Collections +{ + /// + /// Dans cette classe, nous n'utilisons pas de Deserialization Hook. + /// Lors de la désérialisation, l'initialiseur de isAlive et le constructeur de Animal ne sont pas appelés. + /// isAlive prend donc la valeur false par défaut, alors qu'il aurait dû prendre la valeur true imposée pour une construction. + /// (Note : initialiser isAlive dans l'initialiseur ET dans le constructeur n'a pas de sens, et a juste ici pour objectif de vous montrer que les deux sont by-passés) + /// + [DataContract] + class Animal + { + [DataMember] + public string Nom + { + get; + set; + } + + [DataMember] + public string Bruit + { + get; + set; + } + + private bool isAlive = true; + + public Animal(string nom, string bruit) + { + isAlive = true; + Nom = nom; + Bruit = bruit; + } + + public override string ToString() + { + return $"{Nom} ({Bruit}) isAlive: {isAlive}"; + } + } +} diff --git a/p07_Persistance/ex_038_005_DataContract_Hooks/Animal2.cs b/p07_Persistance/ex_038_005_DataContract_Hooks/Animal2.cs new file mode 100644 index 0000000..eeb4019 --- /dev/null +++ b/p07_Persistance/ex_038_005_DataContract_Hooks/Animal2.cs @@ -0,0 +1,67 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Animal2.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System.Runtime.Serialization; + +namespace ex_038_004_DataContract_Collections +{ + /// + /// Dans cette classe, nous utilisons un Deserialization Hook. + /// Lors de la désérialisation, l'initialiseur de isAlive et le constructeur de Animal ne sont pas appelés. + /// Mais la méthode décorée par [OnDeserializing] est, elle, appelée juste avant la désérialisation. + /// (Cette méthode prend un StreamingContext en paramètre, mais il ne sert à rien. Il est utile dans le cas de sérialisation/désérialisation binaire et + /// a été gardé ici pour des raisons de symétrie.) + /// isAlive prend donc la valeur false par défaut, mais lors de l'appel de la méthode juste avant la désérialisation, il est setté à true. + /// + /// Les autres décorateurs Serialization et Deserialization Hook sont : + /// [OnSerializing] pour indiquer que la méthode doit être appelée juste avant la sérialisation + /// [OnSerialized] pour indiquer que la méthode doit être appelée juste après la sérialisation + /// [OnDeserialized] pour indiquer que la méthode doit être appelée juste après la désérialisation. + /// + /// (Note : initialiser isAlive dans l'initialiseur ET dans le constructeur n'a pas de sens, et a juste ici pour objectif de vous montrer que les deux sont by-passés) + /// + [DataContract] + class Animal2 + { + [DataMember] + public string Nom + { + get; + set; + } + + [DataMember] + public string Bruit + { + get; + set; + } + + private bool isAlive = true; + + public Animal2(string nom, string bruit) + { + Init(); + Nom = nom; + Bruit = bruit; + } + + [OnDeserializing] + void Init(StreamingContext sc = new StreamingContext()) + { + isAlive = true; + } + public override string ToString() + { + return $"{Nom} ({Bruit}) isAlive: {isAlive}"; + } + } +} diff --git a/p07_Persistance/ex_038_005_DataContract_Hooks/Program.cs b/p07_Persistance/ex_038_005_DataContract_Hooks/Program.cs new file mode 100644 index 0000000..b3890a3 --- /dev/null +++ b/p07_Persistance/ex_038_005_DataContract_Hooks/Program.cs @@ -0,0 +1,77 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using ex_038_004_DataContract_Collections; +using System.IO; +using System.Runtime.Serialization; +using System.Xml; +using static System.Console; + +namespace ex_038_005_DataContract_Hooks +{ + class Program + { + /// + /// Parfois, certaines méthodes doivent être exécutées juste avant ou juste après la sérialisation ou la désérialisation. + /// On les appelle les Serialization and Deserialization Hooks. + /// Cet exemple montre un cas d'utilisation d'un hook juste avant désérialisation. La classe Animal ne l'utilise pas alors que la classe Animal2 l'utilise. + /// Toutes les deux possèdent un membre privé isAlive de type bool initialisé à true (aussi bien dans l'initialiseur que dans le constructeur). + /// Or, la désérialisation by-pass les initialiseurs de membres et les constructeurs. En conséquence, sans l'utilisation d'un hook, ce membre reste à false + /// lors de la désérialisation. + /// Explorez les classes Animal et Animal2 pour mieux comprendre. + /// + /// + static void Main(string[] args) + { + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + + Animal jojo = new Animal("jojo", "pfffff"); + Animal2 jojo2 = new Animal2("jojo2", "pfffff"); + + var serializer = new DataContractSerializer(typeof(Animal)); + + XmlWriterSettings settings = new XmlWriterSettings() { Indent = true }; + using (TextWriter tw = File.CreateText("animal.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer.WriteObject(writer, jojo); + } + + Animal jojoDésérialisé; + using (Stream s = File.OpenRead("animal.xml")) + { + jojoDésérialisé = serializer.ReadObject(s) as Animal; + } + + WriteLine(jojoDésérialisé); + + + var serializer2 = new DataContractSerializer(typeof(Animal2)); + + using (TextWriter tw = File.CreateText("animal2.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + serializer2.WriteObject(writer, jojo2); + } + + Animal2 jojoDésérialisé2; + using (Stream s = File.OpenRead("animal2.xml")) + { + jojoDésérialisé2 = serializer2.ReadObject(s) as Animal2; + } + + WriteLine(jojoDésérialisé2); + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_038_005_DataContract_Hooks/XML/.gitignore b/p07_Persistance/ex_038_005_DataContract_Hooks/XML/.gitignore new file mode 100644 index 0000000..250c9bc --- /dev/null +++ b/p07_Persistance/ex_038_005_DataContract_Hooks/XML/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory + +# Except this file +!.gitignore \ No newline at end of file diff --git a/p07_Persistance/ex_038_005_DataContract_Hooks/ex_038_005_DataContract_Hooks.csproj b/p07_Persistance/ex_038_005_DataContract_Hooks/ex_038_005_DataContract_Hooks.csproj new file mode 100644 index 0000000..3d80480 --- /dev/null +++ b/p07_Persistance/ex_038_005_DataContract_Hooks/ex_038_005_DataContract_Hooks.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_038_005_DataContract_Hooks + Exe + ex_038_005_DataContract_Hooks + 6.0.6 + false + false + false + + + + + diff --git a/p07_Persistance/ex_038_006_Binary_Serializable/Nounours.cs b/p07_Persistance/ex_038_006_Binary_Serializable/Nounours.cs new file mode 100644 index 0000000..803bc5d --- /dev/null +++ b/p07_Persistance/ex_038_006_Binary_Serializable/Nounours.cs @@ -0,0 +1,133 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace ex_038_006_Binary_Serializable +{ + /// + /// Pour que Nounours soit sérialisable/désérialisable avec un Binary Serializer, il faut décorer le type avec l'attribut [Serializable] + /// 1) pour cela, il faut ajouter [Serializable] à la définition du type comme ci-dessous. + /// 2) contrairement au DataContract Serializer, on ne rajoute pas d'attributs pour chaque membre à sérialiser. On n'en rajoute que pour ne pas sérialiser. + /// L'attribut à ajouter dans ce cas est [NonSerialized]. Tous les autres membres publics ou privés sont sérialisés. + /// + /// Attention en conséquence aux propriétés automatiques : puisqu'un membre est créé par le compilateur, celui-ci est sérialisé, mais son nom peut changer à compilation. + /// Il faut donc éviter les propriétés automatiques qui doivent être sérialisées. + /// + /// Il faut également faire attention aux membres de types collection (et en particulier aux types abstraits qui sont désérialisés en Array) comme pour les DataContractSerializers. + /// + /// Enfin, comme pour le DataContractSerializer, on trouve les 4 hooks : [OnDeserializing], [OnDeserialized], [OnSerializing] et [OnSerialized] + /// (enlevez l'attribut [OnDeserializing] devant la méthode Init pour constater les dégâts) + /// + [Serializable] + public class Nounours + { + public string Nom + { + get { return nom; } + set { nom = value; } + } + private string nom; + + public DateTime Naissance + { + get { return naissance; } + set { naissance = value; } + } + private DateTime naissance; + + public int NbPoils + { + get; + set; + } + + [NonSerialized] + private int entierQuiSertARienMaisQuOnNeVeutPasSerialiser = 42; + + public List Amis + { + get; + set; + } + + public Nounours() + { + Init(); + Amis = new List(); + } + + [OnDeserializing] + void Init(StreamingContext sc = new StreamingContext()) + { + entierQuiSertARienMaisQuOnNeVeutPasSerialiser = 42; + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.Naissance == other.Naissance); + } + + public override string ToString() + { + string amisStr = String.Empty; + if(Amis.Count > 0) + { + amisStr = $", amis : {Amis.Select(nounours => nounours.Nom).Aggregate((noms, n) => $"{noms} {n}")}"; + } + return $"{Nom} ({Naissance:dd/MM/yyyy}, {NbPoils} poils{amisStr}, 42? {entierQuiSertARienMaisQuOnNeVeutPasSerialiser})"; + } + + } +} diff --git a/p07_Persistance/ex_038_006_Binary_Serializable/Program.cs b/p07_Persistance/ex_038_006_Binary_Serializable/Program.cs new file mode 100644 index 0000000..725c325 --- /dev/null +++ b/p07_Persistance/ex_038_006_Binary_Serializable/Program.cs @@ -0,0 +1,86 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-07 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using static System.Console; + +namespace ex_038_006_Binary_Serializable +{ + /// + /// + /// + class Program + { + static void Main(string[] args) + { + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//..//ex_038_006_Binary_Serializable", "result")); + + Nounours chewie = new Nounours() + { + Nom = "Chewbacca", + Naissance = new DateTime(1977, 5, 27), + NbPoils = 1234567 + }; + + Nounours yoda = new Nounours() + { + Nom = "Yoda", + Naissance = new DateTime(1980, 5, 21), + NbPoils = 3 + }; + + Nounours ewok = new Nounours() + { + Nom = "Ewok", + Naissance = new DateTime(1983, 5, 25), + NbPoils = 3456789 + }; + + chewie.Amis.Add(yoda); + chewie.Amis.Add(ewok); + + WriteLine(chewie); + + + //ATTENTION : pour que le Binary Serializer fonctionne, vous devez avoir décoré l'objet à sérialiser ! + //cf. Nounours.cs + + + //1. Sérialisation d'un chewie en binaire avec la méthode par défaut + //On construit le sérialiseur binaire en précisant le formatter (BinaryFormatter ou SoapFormatter) + //- le formatter binaire est le plus efficace des deux et permet d'obtenir la sortie la plus légère + //- le formatter Soap permet d'obtenir un formatage dans le style du protocole SOAP. + // Attention, il ne prend pas en charge la sérialisation des types génériques comme List ! + string file = "nounours.bin"; + IFormatter formatter = new BinaryFormatter(); + using (FileStream stream = File.Create(file)) + { + formatter.Serialize(stream, chewie); + } + + //- pour désérialiser, on crée le flux (de préférence avec using) en lecture + //- on appelle Deserialize + Nounours nounours2; + using (FileStream stream = File.OpenRead(file)) + { + nounours2 = formatter.Deserialize(stream) as Nounours; + } + + WriteLine(nounours2); + + WriteLine("\n\nLe dossier result a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_038_006_Binary_Serializable/ex_038_006_Binary_Serializable.csproj b/p07_Persistance/ex_038_006_Binary_Serializable/ex_038_006_Binary_Serializable.csproj new file mode 100644 index 0000000..41f1d5a --- /dev/null +++ b/p07_Persistance/ex_038_006_Binary_Serializable/ex_038_006_Binary_Serializable.csproj @@ -0,0 +1,8 @@ + + + + Exe + net6.0 + + + diff --git a/p07_Persistance/ex_038_006_Binary_Serializable/result/.gitignore b/p07_Persistance/ex_038_006_Binary_Serializable/result/.gitignore new file mode 100644 index 0000000..6495aa5 --- /dev/null +++ b/p07_Persistance/ex_038_006_Binary_Serializable/result/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory + +# Except this file +!.gitignore \ No newline at end of file diff --git a/p07_Persistance/ex_038_007_XmlSerializer/Animal.cs b/p07_Persistance/ex_038_007_XmlSerializer/Animal.cs new file mode 100644 index 0000000..e0f90dd --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/Animal.cs @@ -0,0 +1,67 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Animal.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// +// ======================================================================== + +using System.Xml.Serialization; + +namespace ex_038_007_XmlSerializer +{ + /// + /// Les attributs XmlInclude permettent d'informer le XmlSerializer qu'il existe des classes filles d'Animal qui pourront être sérialisées + /// Tous les membres et propriétés publiques sont sérialisés + /// + [XmlInclude(typeof(Chat))] + [XmlInclude(typeof(Chien))] + public class Animal + { + /// + /// par défaut, un membre ou une propriété est sérialisé en élément XML. Mais vous pouvez forcer sa sérialisation en attribut avec XmlAttribute. + /// Vous pouvez en profiter pour modifier le nom de l'attribut XML (ici on le passe en minuscules). + /// + [XmlAttribute(AttributeName = "nom")] + public string Nom + { + get; + set; + } + + /// + /// XmlElement n'est pas obligatoire mais il donne accès à quelques options comme Order, le nom de l'élément... + /// + [XmlElement(ElementName = "bruit")] + public string Bruit + { + get; + set; + } + + /// + /// comme pour le BinarySerializer et contrairement au DataContractSerializer, il faut préciser avec XmlIgnore qu'on ne veut pas sérialiser un membre ou une propriété. + /// + [XmlIgnore] + public int UnePropriétéQuOnNeVeutPasSerialiser + { + get; + set; + } = 42; + + public Animal(string nom, string bruit) + { + Nom = nom; + Bruit = bruit; + } + + /// + /// pour utiliser XmlSerializer, les types doivent avoir un constructeur par défaut + /// + public Animal() + { } + } +} diff --git a/p07_Persistance/ex_038_007_XmlSerializer/AnimalList.cs b/p07_Persistance/ex_038_007_XmlSerializer/AnimalList.cs new file mode 100644 index 0000000..7290794 --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/AnimalList.cs @@ -0,0 +1,33 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AnimalList.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_038_007_XmlSerializer +{ + /// + /// AnimalList est une classe qui dérive d'une collection. + /// Notez qu'il est parfaitement sérialisé. + /// + public class AnimalList : List + { + /// + /// pour utiliser XmlSerializer, les types doivent avoir un constructeur par défaut + /// + public AnimalList() + { + Add(new Chat("GrosMinet", TimeSpan.FromHours(3))); + Add(new Oiseau("Titi", TimeSpan.FromHours(1))); + Add(new Chien("Idefix", 50)); + } + } +} diff --git a/p07_Persistance/ex_038_007_XmlSerializer/Chat.cs b/p07_Persistance/ex_038_007_XmlSerializer/Chat.cs new file mode 100644 index 0000000..231f3a1 --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/Chat.cs @@ -0,0 +1,37 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chat.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// +// ======================================================================== + +using System; + +namespace ex_038_007_XmlSerializer +{ + public class Chat : Animal + { + public TimeSpan DuréeSieste + { + get; + set; + } + + public Chat(string name, TimeSpan duréeSieste) : base(name, "Miaou") + { + DuréeSieste = duréeSieste; + } + + /// + /// pour utiliser XmlSerializer, les types doivent avoir un constructeur par défaut + /// + public Chat() + { + + } + } +} diff --git a/p07_Persistance/ex_038_007_XmlSerializer/Chien.cs b/p07_Persistance/ex_038_007_XmlSerializer/Chien.cs new file mode 100644 index 0000000..6767c7a --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/Chien.cs @@ -0,0 +1,33 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Chien.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// +// ======================================================================== + +namespace ex_038_007_XmlSerializer +{ + public class Chien : Animal + { + public int NbOsRongés + { + get; + set; + } + + public Chien(string name, int nbOsRongés) : base(name, "Wouf Wouf") + { + NbOsRongés = nbOsRongés; + } + + /// + /// pour utiliser XmlSerializer, les types doivent avoir un constructeur par défaut + /// + public Chien() + { } + } +} diff --git a/p07_Persistance/ex_038_007_XmlSerializer/Ménagerie.cs b/p07_Persistance/ex_038_007_XmlSerializer/Ménagerie.cs new file mode 100644 index 0000000..c12b52d --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/Ménagerie.cs @@ -0,0 +1,59 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Ménagerie.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace ex_038_007_XmlSerializer +{ + /// + /// Ménagerie contient deux collections : une de Chat et une de Animal. + /// Ces collections sont privées (List et List). + /// Si on les encapsule en lecture seule par des propriétés publiques de type IEnumerable, on ne pourra pas les sérialiser. + /// XmlSerializer ne sait pas sérialiser ces types. Il veut pouvoir les désérialiser. + /// + /// Notez également qu'une collection d'un type père se sérialise parfaitement en sérialisant les items de types fils. + /// + public class Ménagerie + { + public string Nom { get; set; } + + public List Chats => chats; + + private List chats = new List { + new Chat("Isidore", TimeSpan.FromHours(4)), + new Chat("Garfield", TimeSpan.FromHours(12)), + new Chat("GrosMinet", TimeSpan.FromHours(3))}; + + /// + /// XmlArray vous permet de modifier le nom extérieur de la collection + /// XmlArrayItem vous permet de modifier le nom d'un élément fils en fonction de son type + /// + [XmlArray(ElementName = "animaux")] + [XmlArrayItem(ElementName = "chat", Type = typeof(Chat))] + [XmlArrayItem(ElementName = "chien", Type = typeof(Chien))] + [XmlArrayItem(ElementName = "oiseau", Type = typeof(Oiseau))] + public List Animaux => animaux; + + private List animaux = new List + { + new Chat("GrosMinet", TimeSpan.FromHours(3)), + new Oiseau("Titi", TimeSpan.FromHours(1)), + new Chien("Idefix", 50) + }; + + /// + /// pour utiliser XmlSerializer, les types doivent avoir un constructeur par défaut + /// + public Ménagerie() { } + } +} diff --git a/p07_Persistance/ex_038_007_XmlSerializer/Oiseau.cs b/p07_Persistance/ex_038_007_XmlSerializer/Oiseau.cs new file mode 100644 index 0000000..1fd93c0 --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/Oiseau.cs @@ -0,0 +1,33 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Oiseau.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// +// ======================================================================== + +using System; + +namespace ex_038_007_XmlSerializer +{ + public class Oiseau : Animal + { + public TimeSpan TempsDeVol + { + get; set; + } + + public Oiseau(string nom, TimeSpan tempsDeVol) : base(nom, "Cui Cui") + { + TempsDeVol = tempsDeVol; + } + + /// + /// pour utiliser XmlSerializer, les types doivent avoir un constructeur par défaut + /// + public Oiseau() { } + } +} diff --git a/p07_Persistance/ex_038_007_XmlSerializer/Program.cs b/p07_Persistance/ex_038_007_XmlSerializer/Program.cs new file mode 100644 index 0000000..37cd5fb --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/Program.cs @@ -0,0 +1,117 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.Serialization; +using static System.Console; + +namespace ex_038_007_XmlSerializer +{ + class Program + { + /// + /// le XmlSerializer peut sérialiser et désérialiser en XML. + /// Voici quelques exemples : + /// + /// + static void Main(string[] args) + { + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + + List animaux = new List + { + new Chat("GrosMinet", TimeSpan.FromHours(3)), + new Oiseau("Titi", TimeSpan.FromHours(1)), + new Chien("Idefix", 50) + }; + + // ===1=== + //on sérialise ici une collection d'Animal. Il suffit juste de donner le type de l'élément à sérialiser au sérialiseur, i.e. ici List + //Comme Animal connait les types Chat et Chien (grâce à XmlInclude), pas besoin de les donner au sérialiseur. + //Puisque Animal ne connait pas le type Oiseau, il faut préciser au sérialiseur qu'il peut tomber dessus. + XmlSerializer serializerListAnimal = new XmlSerializer(typeof(List), new Type[] { typeof(Oiseau) }); + + //sérialisation + using (Stream stream = File.Create("List_Animal.xml")) + { + serializerListAnimal.Serialize(stream, animaux); + } + + //désérialisation + List deserialized; + using (Stream stream = File.OpenRead("List_Animal.xml")) + { + deserialized = serializerListAnimal.Deserialize(stream) as List; + } + + foreach (var a in deserialized) + { + WriteLine(a); + } + + + // ===2=== + //Ici, on va sérialiser une classe Ménagerie qui contient deux collections : une de Chat et une de Animal + //Notez encore une fois qu'on précise au sérialiseur qu'il peut tomber sur des Oiseau + //Lisez les commentaires dans Ménagerie pour plus d'explications. + Ménagerie ménagerie = new Ménagerie { Nom = "mon Zoo" }; + + XmlSerializer serializerMénagerie = new XmlSerializer(typeof(Ménagerie), new Type[] { typeof(Oiseau) }); + + //sérialisation + using (Stream stream = File.Create("Ménagerie.xml")) + { + serializerMénagerie.Serialize(stream, ménagerie); + } + + //désérialisation + Ménagerie deserialized2; + using (Stream stream = File.OpenRead("Ménagerie.xml")) + { + deserialized2 = serializerMénagerie.Deserialize(stream) as Ménagerie; + } + + WriteLine(deserialized2); + + + // ===3=== + //Enfin, AnimalList est une classe qui dérive d'une collection. + //Elle utilise un attribut légèrement différent. + //Lisez les commentaires de AnimalList pour le découvrir. + AnimalList animalList = new AnimalList(); + + XmlSerializer serializerAnimalList = new XmlSerializer(typeof(AnimalList), new Type[] { typeof(Oiseau) }); + + //sérialisation + using (Stream stream = File.Create("AnimalList.xml")) + { + serializerAnimalList.Serialize(stream, animalList); + } + + //désérialisation + Ménagerie deserialized3; + using (Stream stream = File.OpenRead("AnimalList.xml")) + { + deserialized3 = serializerAnimalList.Deserialize(stream) as Ménagerie; + } + + foreach (var a in deserialized) + { + WriteLine(a); + } + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_038_007_XmlSerializer/XML/.gitignore b/p07_Persistance/ex_038_007_XmlSerializer/XML/.gitignore new file mode 100644 index 0000000..250c9bc --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/XML/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory + +# Except this file +!.gitignore \ No newline at end of file diff --git a/p07_Persistance/ex_038_007_XmlSerializer/ex_038_007_XmlSerializer.csproj b/p07_Persistance/ex_038_007_XmlSerializer/ex_038_007_XmlSerializer.csproj new file mode 100644 index 0000000..e2787a6 --- /dev/null +++ b/p07_Persistance/ex_038_007_XmlSerializer/ex_038_007_XmlSerializer.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_038_007_XmlSerializer + Exe + ex_038_007_XmlSerializer + 6.0.6 + false + false + false + + + + + diff --git a/p07_Persistance/ex_038_008_IXmlSerializable/Album.cs b/p07_Persistance/ex_038_008_IXmlSerializable/Album.cs new file mode 100644 index 0000000..2787932 --- /dev/null +++ b/p07_Persistance/ex_038_008_IXmlSerializable/Album.cs @@ -0,0 +1,77 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Album.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// +// ======================================================================== + +using System; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +namespace ex_038_008_IXmlSerializable +{ + /// + /// Album est sérialisable en utilisant DataContractSerializer + /// Il possède deux références vers des artistes (pas de collection pour le moment, ce sera traité dans l'exemple suivant). + /// + class Album : IXmlSerializable + { + public string Titre + { + get; set; + } + + public Artiste Artiste + { + get; set; + } + + public int AnnéeDeSortie + { + get; set; + } + + public Album() + { + } + + public Album(XmlReader reader) + { + ReadXml(reader); + } + + public XmlSchema GetSchema() + { + return null; + } + + public void ReadXml(XmlReader reader) + { + Titre = reader["titre"]; + reader.ReadStartElement("album"); + AnnéeDeSortie = reader.ReadElementContentAsInt("annéeDeSortie", ""); + Artiste = new Artiste(reader); + reader.ReadEndElement(); + } + + public void WriteXml(XmlWriter writer) + { + writer.WriteAttributeString("titre", Titre); + writer.WriteElementString("annéeDeSortie", AnnéeDeSortie.ToString()); + writer.WriteStartElement("artiste"); + Artiste.WriteXml(writer); + writer.WriteEndElement(); + } + + public override string ToString() + { + return $"Album: Titre: {Titre}, Year: {AnnéeDeSortie}, Artist: {Artiste}"; + } + } +} diff --git a/p07_Persistance/ex_038_008_IXmlSerializable/Artiste.cs b/p07_Persistance/ex_038_008_IXmlSerializable/Artiste.cs new file mode 100644 index 0000000..e956714 --- /dev/null +++ b/p07_Persistance/ex_038_008_IXmlSerializable/Artiste.cs @@ -0,0 +1,80 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Artiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// +// ======================================================================== + +using System; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +namespace ex_038_008_IXmlSerializable +{ + /// + /// Artiste est sérialisable en utilisant DataContractSerializer. + /// + class Artiste : IXmlSerializable + { + public string Prénom + { + get; set; + } + + public string Nom + { + get; set; + } + + public DateTime Naissance + { + get; set; + } + + public string Instrument + { + get; set; + } + + public Artiste() + { } + + public Artiste(XmlReader reader) + { + ReadXml(reader); + } + + public XmlSchema GetSchema() + { + return null; + } + + public void ReadXml(XmlReader reader) + { + Nom = reader["nom"]; + Prénom = reader["prénom"]; + Naissance = XmlConvert.ToDateTime(reader["naissance"], XmlDateTimeSerializationMode.Utc); + reader.ReadStartElement(); + Instrument = reader.ReadElementContentAsString("instrument", ""); + reader.ReadEndElement(); + } + + public void WriteXml(XmlWriter writer) + { + writer.WriteAttributeString("nom", Nom); + writer.WriteAttributeString("prénom", Prénom); + writer.WriteAttributeString("naissance", XmlConvert.ToString(Naissance, XmlDateTimeSerializationMode.Utc)); + writer.WriteElementString("instrument", Instrument); + } + + public override string ToString() + { + return $"{Prénom} {Nom} ({Instrument}, {Naissance.ToString("d")})"; + } + } +} diff --git a/p07_Persistance/ex_038_008_IXmlSerializable/Program.cs b/p07_Persistance/ex_038_008_IXmlSerializable/Program.cs new file mode 100644 index 0000000..3f7b05a --- /dev/null +++ b/p07_Persistance/ex_038_008_IXmlSerializable/Program.cs @@ -0,0 +1,59 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Artiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-12 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System; +using System.IO; +using System.Xml; +using static System.Console; + +namespace ex_038_008_IXmlSerializable +{ + class Program + { + static void Main(string[] args) + { + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + + Artiste bojan = new Artiste { Prénom = "Bojan", Nom = "Z", Naissance = new DateTime(1968, 2, 2), Instrument = "Piano" }; + Album duo = new Album { Titre = "Duo", AnnéeDeSortie = 2015, Artiste = bojan }; + + XmlWriterSettings writerSettings = new XmlWriterSettings(); + writerSettings.Indent = true; + + using (TextWriter tw = File.CreateText("album.xml")) + { + using (XmlWriter writer = XmlWriter.Create(tw, writerSettings)) + { + writer.WriteStartDocument(); + writer.WriteStartElement("album", ""); + duo.WriteXml(writer); + writer.WriteEndElement(); + writer.WriteEndDocument(); + } + } + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreWhitespace = true; + settings.IgnoreComments = true; + settings.IgnoreProcessingInstructions = true; + + using (XmlReader reader = XmlReader.Create("album.xml", settings)) + { + while (reader.NodeType != XmlNodeType.Element) reader.Read(); + Album a = new Album(reader); + WriteLine(a); + } + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_038_008_IXmlSerializable/XML/.gitignore b/p07_Persistance/ex_038_008_IXmlSerializable/XML/.gitignore new file mode 100644 index 0000000..250c9bc --- /dev/null +++ b/p07_Persistance/ex_038_008_IXmlSerializable/XML/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory + +# Except this file +!.gitignore \ No newline at end of file diff --git a/p07_Persistance/ex_038_008_IXmlSerializable/ex_038_008_IXmlSerializable.csproj b/p07_Persistance/ex_038_008_IXmlSerializable/ex_038_008_IXmlSerializable.csproj new file mode 100644 index 0000000..0ae4e45 --- /dev/null +++ b/p07_Persistance/ex_038_008_IXmlSerializable/ex_038_008_IXmlSerializable.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_038_008_IXmlSerializable + Exe + ex_038_008_IXmlSerializable + 6.0.6 + false + false + false + + + + + diff --git a/p07_Persistance/ex_039_001_XDOM_bases/Program.cs b/p07_Persistance/ex_039_001_XDOM_bases/Program.cs new file mode 100644 index 0000000..fcd90f8 --- /dev/null +++ b/p07_Persistance/ex_039_001_XDOM_bases/Program.cs @@ -0,0 +1,62 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-13 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System.IO; +using System.Xml; +using System.Xml.Linq; +using static System.Console; + +namespace ex_039_001_XDOM_bases +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + + XDocument volcansFichier = XDocument.Load("volcans.xml"); + WriteLine(volcansFichier); + + //settings pour que le fichier écrit soit indenté + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + + using (TextWriter tw = File.CreateText("volcansSave.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + volcansFichier.Save(writer); + } + + XElement testVolcan = XElement.Parse( + @" + Puy de Dôme + P6000Y + 1465 + + 45.7723 + 2.9658 + + "); + WriteLine(testVolcan); + + using (TextWriter tw = File.CreateText("unVolcan.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + volcansFichier.Save(writer); + } + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + } +} diff --git a/p07_Persistance/ex_039_001_XDOM_bases/XML/volcans.xml b/p07_Persistance/ex_039_001_XDOM_bases/XML/volcans.xml new file mode 100644 index 0000000..725eec3 --- /dev/null +++ b/p07_Persistance/ex_039_001_XDOM_bases/XML/volcans.xml @@ -0,0 +1,90 @@ + + + + + + 2010-12-10 + Piton de la Fournaise + 2632 + + -21.2425 + 55.708889 + + Basalte + + + Etna + 2010/11/14 + 3345 + + 37.734 + 15.004 + + + + 04/04/1944 + 1281 + + 40.821389 + 14.425556 + + Vesuve + Téphrites trachytes phonolites + + + 30 janvier 2011 + Mayon + 2462 + + 13.257 + 123.685 + + + + 6000 ans + 1465 + + 45.7723 + 2.9658 + + Puy de Dôme + + + 2009-06-21 + 1512 + + 48.09 + 153.2 + + Sarytchev + Andésite + + + 2010-10-27 + 1666 + + 63.63 + -19.62 + + Basalte + + + Pinatubo + juillet 1993 + 1486 + + 15.13 + 120.35 + + Andésite Basalte + + diff --git a/p07_Persistance/ex_039_001_XDOM_bases/ex_039_001_XDOM_bases.csproj b/p07_Persistance/ex_039_001_XDOM_bases/ex_039_001_XDOM_bases.csproj new file mode 100644 index 0000000..5039a11 --- /dev/null +++ b/p07_Persistance/ex_039_001_XDOM_bases/ex_039_001_XDOM_bases.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_039_001_XDOM_bases + Exe + ex_039_001_XDOM_bases + 6.0.6 + false + false + false + + diff --git a/p07_Persistance/ex_039_002_LINQ_to_XML/Program.cs b/p07_Persistance/ex_039_002_LINQ_to_XML/Program.cs new file mode 100644 index 0000000..9ec7978 --- /dev/null +++ b/p07_Persistance/ex_039_002_LINQ_to_XML/Program.cs @@ -0,0 +1,116 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Volcan.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-13 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using System.Xml.Linq; +using static System.Console; + +namespace ex_039_002_LINQ_to_XML +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//XML")); + + LireVolcansInXMLFile(); + WriteLine("VOLCANS LUS :"); + foreach (var volcan in listeVolcans) + { + WriteLine(volcan); + } + WriteLine("".PadRight(WindowWidth - 1, '*')); + + var pariou = new Volcan() + { + Nom = "Puy de Pariou", + Altitude = 1209, + Latitude = 45.795462f, + Longitude = 2.970257f, + Pays = "France", + }; + pariou.AjouterRoches("Trachy-basalte", "trachy-andésite", "trachyte"); + listeVolcans.Add(pariou); + + WriteLine("VOLCANS APRES AJOUT :"); + foreach (var volcan in listeVolcans) + { + WriteLine(volcan); + } + WriteLine("".PadRight(WindowWidth - 1, '*')); + + EcrireVolcansInXMLFile(); + + WriteLine("\n\nLe dossier XML a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + + static List listeVolcans = new List(); + + static void LireVolcansInXMLFile() + { + XDocument volcansFichier = XDocument.Load("volcans.xml"); + + listeVolcans = volcansFichier.Descendants("volcan") + .Select(eltVolcan => new Volcan() + { + Pays = eltVolcan.Attribute("pays").Value, + Nom = eltVolcan.Element("nom").Value, + Altitude = XmlConvert.ToSingle(eltVolcan.Element("altitude").Value), + Latitude = XmlConvert.ToSingle(eltVolcan.Element("coordonnées").Element("latitude").Value), + Longitude = XmlConvert.ToSingle(eltVolcan.Element("coordonnées").Element("longitude").Value) + }).ToList(); + + foreach (var volcan in listeVolcans) + { + var rochesElt = volcansFichier.Descendants("volcan") + .Single(elt => elt.Element("nom").Value == volcan.Nom) + .Element("roches"); + if (rochesElt == null) + { + continue; + } + volcan.AjouterRoches(rochesElt.Value.Split()); + } + } + + private static void EcrireVolcansInXMLFile() + { + XDocument volcansFichier = new XDocument(); + + var volcansElts = listeVolcans.Select(volcan => new XElement("volcan", + new XAttribute("pays", volcan.Pays), + new XElement("nom", volcan.Nom), + new XElement("altitude", XmlConvert.ToString(volcan.Altitude)), + new XElement("coordonnées", + new XElement("latitude", XmlConvert.ToString(volcan.Latitude)), + new XElement("longitude", XmlConvert.ToString(volcan.Longitude))), + new XElement("roches", volcan.Roches.Count() > 0 ? volcan.Roches.Aggregate((stringRoche, nextRoche) => $"{stringRoche} {nextRoche}") : ""))); + + volcansFichier.Add(new XElement("volcans", volcansElts)); + + //settings pour que le fichier écrit soit indenté + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + + using (TextWriter tw = File.CreateText("volcansAjout.xml")) + using (XmlWriter writer = XmlWriter.Create(tw, settings)) + { + volcansFichier.Save(writer); + } + } + } +} diff --git a/p07_Persistance/ex_039_002_LINQ_to_XML/Volcan.cs b/p07_Persistance/ex_039_002_LINQ_to_XML/Volcan.cs new file mode 100644 index 0000000..2f1e3a4 --- /dev/null +++ b/p07_Persistance/ex_039_002_LINQ_to_XML/Volcan.cs @@ -0,0 +1,108 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Volcan.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-13 +// +// ======================================================================== + +using System.Collections.Generic; +using System.Text; + +namespace ex_039_002_LINQ_to_XML +{ + /// + /// classe de stockage pour les données d'un volcan + /// + public class Volcan + { + /// + /// nom du volcan + /// + public string Nom + { + get; + set; + } + + /// + /// pays où se trouve ce volcan + /// + public string Pays + { + get; + set; + } + + /// + /// altitude de ce volcan + /// + public float Altitude + { + get; + set; + } + + /// + /// latitude de ce volcan + /// + public float Latitude + { + get; + set; + } + + /// + /// longitude de ce volcan + /// + public float Longitude + { + get; + set; + } + + /// + /// differentes roches de ce volcan + /// + public IEnumerable Roches + { + get + { + return mRoches; + } + } + /// + private List mRoches = new List(); + + /// + /// ajoute une roche à la collection de roches de ce volcan + /// + /// + public void AjouterRoches(params string[] roches) + { + mRoches.AddRange(roches); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat($"Nom : {Nom}\n"); + sb.AppendFormat($"Altitude : {Altitude} mètres\n"); + + sb.AppendLine(); + sb.AppendFormat($"Coordonnées : {Latitude} ; {Longitude}\n"); + + if (mRoches.Count > 0) + { + sb.AppendLine("Roches :"); + mRoches.ForEach(rock => sb.AppendFormat($"\t{rock}\n")); + } + + return sb.ToString(); + } + } +} diff --git a/p07_Persistance/ex_039_002_LINQ_to_XML/XML/volcans.xml b/p07_Persistance/ex_039_002_LINQ_to_XML/XML/volcans.xml new file mode 100644 index 0000000..0118693 --- /dev/null +++ b/p07_Persistance/ex_039_002_LINQ_to_XML/XML/volcans.xml @@ -0,0 +1,83 @@ + + + + + + Piton de la Fournaise + 2632 + + -21.2425 + 55.708889 + + Basalte + + + Etna + 3345 + + 37.734 + 15.004 + + + + 1281 + + 40.821389 + 14.425556 + + Vesuve + Téphrites trachytes phonolites + + + Mayon + 2462 + + 13.257 + 123.685 + + + + 1465 + + 45.7723 + 2.9658 + + Puy de Dôme + + + 1512 + + 48.09 + 153.2 + + Sarytchev + Andésite + + + 1666 + + 63.63 + -19.62 + + Eyjafjöll + Basalte + + + Pinatubo + 1486 + + 15.13 + 120.35 + + Andésite Basalte + + diff --git a/p07_Persistance/ex_039_002_LINQ_to_XML/ex_039_002_LINQ_to_XML.csproj b/p07_Persistance/ex_039_002_LINQ_to_XML/ex_039_002_LINQ_to_XML.csproj new file mode 100644 index 0000000..719f09c --- /dev/null +++ b/p07_Persistance/ex_039_002_LINQ_to_XML/ex_039_002_LINQ_to_XML.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_039_002_LINQ_to_XML + Exe + ex_039_002_LINQ_to_XML + 6.0.6 + false + false + false + + diff --git a/p07_Persistance/ex_040_001_LINQ_to_Json/Json/volcans.json b/p07_Persistance/ex_040_001_LINQ_to_Json/Json/volcans.json new file mode 100644 index 0000000..8a50590 --- /dev/null +++ b/p07_Persistance/ex_040_001_LINQ_to_Json/Json/volcans.json @@ -0,0 +1,100 @@ +{ + "volcans": [ + { + "volcan": { + "pays": "France", + "nom": "Piton de la Fournaise", + "altitude": "2632.0", + "coordonnées": { + "latitude": "-21.2425", + "longitude": "55.70889" + }, + "roches": "Basalte" + } + }, + { + "volcan": { + "pays": "Italie", + "nom": "Etna", + "altitude": "3345.0", + "coordonnées": { + "latitude": "37.734", + "longitude": "15.004" + }, + "roches": "" + } + }, + { + "volcan": { + "pays": "Italie", + "nom": "Vesuve", + "altitude": "1281.0", + "coordonnées": { + "latitude": "40.82139", + "longitude": "14.4255562" + }, + "roches": "Téphrites trachytes phonolites" + } + }, + { + "volcan": { + "pays": "Philippines", + "nom": "Mayon", + "altitude": "2462.0", + "coordonnées": { + "latitude": "13.257", + "longitude": "123.685" + }, + "roches": "" + } + }, + { + "volcan": { + "pays": "France", + "nom": "Puy de Dôme", + "altitude": "1465.0", + "coordonnées": { + "latitude": "45.7723", + "longitude": "2.9658" + }, + "roches": "" + } + }, + { + "volcan": { + "pays": "Russie", + "nom": "Sarytchev", + "altitude": "1512.0", + "coordonnées": { + "latitude": "48.09", + "longitude": "153.2" + }, + "roches": "Andésite" + } + }, + { + "volcan": { + "pays": "Islande", + "nom": "Eyjafjöll", + "altitude": "1666.0", + "coordonnées": { + "latitude": "63.63", + "longitude": "-19.62" + }, + "roches": "Basalte" + } + }, + { + "volcan": { + "pays": "Philippines", + "nom": "Pinatubo", + "altitude": "1486.0", + "coordonnées": { + "latitude": "15.13", + "longitude": "120.35" + }, + "roches": "Andésite Basalte" + } + } + ] +} \ No newline at end of file diff --git a/p07_Persistance/ex_040_001_LINQ_to_Json/Program.cs b/p07_Persistance/ex_040_001_LINQ_to_Json/Program.cs new file mode 100644 index 0000000..7cff480 --- /dev/null +++ b/p07_Persistance/ex_040_001_LINQ_to_Json/Program.cs @@ -0,0 +1,110 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-13 +// Mise à jour : 2019-12-08 +// +// ======================================================================== + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using static System.Console; + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace ex_040_001_LINQ_to_Json +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "..//..//..//Json")); + LireVolcansInXMLFile(); + + WriteLine("VOLCANS LUS :"); + foreach (var volcan in listeVolcans) + { + WriteLine(volcan); + } + WriteLine("".PadRight(WindowWidth - 1, '*')); + + var pariou = new Volcan() + { + Nom = "Puy de Pariou", + Altitude = 1209, + Latitude = 45.795462f, + Longitude = 2.970257f, + Pays = "France", + }; + pariou.AjouterRoches("Trachy-basalte", "trachy-andésite", "trachyte"); + listeVolcans.Add(pariou); + + WriteLine("VOLCANS APRES AJOUT :"); + foreach (var volcan in listeVolcans) + { + WriteLine(volcan); + } + WriteLine("".PadRight(WindowWidth - 1, '*')); + + EcrireVolcansInJsonFile(); + + WriteLine("\n\nLe dossier Json a été mis à jour par l'exécution de ce programme. Jetez un oeil !"); + } + + static List listeVolcans = new List(); + + static void LireVolcansInXMLFile() + { + string jsonText = File.ReadAllText("volcans.json"); + JObject json = JObject.Parse(jsonText); + + listeVolcans = json["volcans"].Select(j => new Volcan() + { + Pays = (string)j["volcan"]["pays"], + Nom = (string)j["volcan"]["nom"], + Altitude = (float)j["volcan"]["altitude"], + Latitude = (float)j["volcan"]["coordonnées"]["latitude"], + Longitude = (float)j["volcan"]["coordonnées"]["longitude"] + }).ToList(); + + foreach (var volcan in listeVolcans) + { + var rochesElt = (string)json["volcans"] + .Single(elt => ((string)elt["volcan"]["nom"]).Equals(volcan.Nom)) + ["volcan"]["roches"]; + if (rochesElt == null) + { + continue; + } + volcan.AjouterRoches(rochesElt.Split()); + } + } + + static void EcrireVolcansInJsonFile() + { + var volcansElts = listeVolcans.Select(volcan => new JObject( + new JProperty("volcan", + new JObject( + new JProperty("pays", volcan.Pays), + new JProperty("nom", volcan.Nom), + new JProperty("altitude", JsonConvert.ToString(volcan.Altitude)), + new JProperty("coordonnées", + new JObject( + new JProperty("latitude", JsonConvert.ToString(volcan.Latitude)), + new JProperty("longitude", JsonConvert.ToString(volcan.Longitude)))), + new JProperty("roches", volcan.Roches.Count() > 0 ? volcan.Roches.Aggregate((stringRoche, nextRoche) => $"{stringRoche} {nextRoche}") : ""))))); + + var volcansFichier = new JObject(new JProperty("volcans", volcansElts)); + + File.WriteAllText("volcans2.json", volcansFichier.ToString()); + } + } +} diff --git a/p07_Persistance/ex_040_001_LINQ_to_Json/Volcan.cs b/p07_Persistance/ex_040_001_LINQ_to_Json/Volcan.cs new file mode 100644 index 0000000..4663af7 --- /dev/null +++ b/p07_Persistance/ex_040_001_LINQ_to_Json/Volcan.cs @@ -0,0 +1,108 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Volcan.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-13 +// +// ======================================================================== + +using System.Collections.Generic; +using System.Text; + +namespace ex_040_001_LINQ_to_Json +{ + /// + /// classe de stockage pour les données d'un volcan + /// + public class Volcan + { + /// + /// nom du volcan + /// + public string Nom + { + get; + set; + } + + /// + /// pays où se trouve ce volcan + /// + public string Pays + { + get; + set; + } + + /// + /// altitude de ce volcan + /// + public float Altitude + { + get; + set; + } + + /// + /// latitude de ce volcan + /// + public float Latitude + { + get; + set; + } + + /// + /// longitude de ce volcan + /// + public float Longitude + { + get; + set; + } + + /// + /// differentes roches de ce volcan + /// + public IEnumerable Roches + { + get + { + return mRoches; + } + } + /// + private List mRoches = new List(); + + /// + /// ajoute une roche à la collection de roches de ce volcan + /// + /// + public void AjouterRoches(params string[] roches) + { + mRoches.AddRange(roches); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat($"Nom : {Nom}\n"); + sb.AppendFormat($"Altitude : {Altitude} mètres\n"); + + sb.AppendLine(); + sb.AppendFormat($"Coordonnées : {Latitude} ; {Longitude}\n"); + + if (mRoches.Count > 0) + { + sb.AppendLine("Roches :"); + mRoches.ForEach(rock => sb.AppendFormat($"\t{rock}\n")); + } + + return sb.ToString(); + } + } +} diff --git a/p07_Persistance/ex_040_001_LINQ_to_Json/ex_040_001_LINQ_to_Json.csproj b/p07_Persistance/ex_040_001_LINQ_to_Json/ex_040_001_LINQ_to_Json.csproj new file mode 100644 index 0000000..2bda6d1 --- /dev/null +++ b/p07_Persistance/ex_040_001_LINQ_to_Json/ex_040_001_LINQ_to_Json.csproj @@ -0,0 +1,15 @@ + + + net6.0 + ex_040_001_LINQ_to_Json + Exe + ex_040_001_LINQ_to_Json + 6.0.6 + false + false + false + + + + + diff --git a/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Album.cs b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Album.cs new file mode 100644 index 0000000..404b7c9 --- /dev/null +++ b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Album.cs @@ -0,0 +1,67 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Album.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; + +namespace ex_042_010_EF_CF_Many_to_Many +{ + /// + /// Album est une classe POCO, i.e. Plain Old CLR Object. + /// Elle a une relation many-many avec la classe Artiste via la propriété Artistes. + /// La clé primaire est générée lors de l'insertion en table. + /// + /// Aujourd'hui (21 octobre 2016), il n'est pas encore possible d'utiliser les annotations de données pour les relations many to many. + /// En conséquence, il faut créer une classe pour la table d'association. + /// Dans la classe Album, on trouve donc une propriété AlbumsArtistes, collection de AlbumArtiste (correspondant à la table d'association). + /// On trouve également une propriété calculée Artistes qui réalise une projection de la collection précédente pour obtenir les artistes, ainsi + /// qu'une méthode AddArtiste rajoutant une ligne dans la table d'association. + /// + [Table("Albums")] + public class Album + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + public string Titre + { + get; set; + } + + public DateTime DateDeSortie + { + get; set; + } + + public virtual IEnumerable Artistes + { + get + { + return AlbumsArtistes.Select(aa => aa.Artiste); + } + } + + public void AddArtiste(Artiste artiste) + { + AlbumsArtistes.Add(new AlbumArtiste() { Album = this, Artiste = artiste }); + } + + public virtual ICollection AlbumsArtistes { get; set; } = new List(); + } +} diff --git a/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/AlbumArtiste.cs b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/AlbumArtiste.cs new file mode 100644 index 0000000..79d5ed2 --- /dev/null +++ b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/AlbumArtiste.cs @@ -0,0 +1,33 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AlbumArtiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace ex_042_010_EF_CF_Many_to_Many +{ + /// + /// table permettant de réaliser la table d'association + /// + public class AlbumArtiste + { + /// + /// un album... + /// + public Album Album { get; set; } + /// + /// ...lié à un artiste + /// + public Artiste Artiste { get; set; } + } +} diff --git a/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/AlbumArtisteDBEntities.cs b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/AlbumArtisteDBEntities.cs new file mode 100644 index 0000000..1eafd9f --- /dev/null +++ b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/AlbumArtisteDBEntities.cs @@ -0,0 +1,55 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AlbumArtisteDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_010_EF_CF_Many_to_Many +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient deux DbSet pour permettre de réaliser des opérations CRUD sur les types T, ici Album et Artiste. + /// + public class AlbumArtisteDBEntities : DbContext + { + public virtual DbSet Artistes { get; set; } + public virtual DbSet Albums { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_010_EF_CF_Many_to_Many.mdf;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + //ajoute deux shadow properties à la classe AlbumArtiste pour qu'elles soient utilisées comme clés étrangères + modelBuilder.Entity().Property("AlbumId"); + modelBuilder.Entity().Property("ArtisteId"); + + //crée une clé primaire à partir des deux propriétés précédentes + modelBuilder.Entity().HasKey("AlbumId", "ArtisteId"); + + //lie l'entité AlbumArtiste à l'entité Album + modelBuilder.Entity() + .HasOne(aa => aa.Album) + .WithMany(album => album.AlbumsArtistes) + .HasForeignKey("AlbumId"); + + //lie l'entité AlbumArtiste à l'entité Artiste + modelBuilder.Entity() + .HasOne(aa => aa.Artiste) + .WithMany(artiste => artiste.AlbumsArtistes) + .HasForeignKey("ArtisteId"); + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Artiste.cs b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Artiste.cs new file mode 100644 index 0000000..0e944a6 --- /dev/null +++ b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Artiste.cs @@ -0,0 +1,76 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Artiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; + +namespace ex_042_010_EF_CF_Many_to_Many +{ + /// + /// Artiste est une classe POCO, i.e. Plain Old CLR Object. + /// Elle a une relation many-many avec la classe Artiste via la propriété Artistes. + /// La clé primaire est générée lors de l'insertion en table. + /// + /// Aujourd'hui (21 octobre 2016), il n'est pas encore possible d'utiliser les annotations de données pour les relations many to many. + /// En conséquence, il faut créer une classe pour la table d'association. + /// Dans la classe Artiste, on trouve donc une propriété AlbumsArtistes, collection de AlbumArtiste (correspondant à la table d'association). + /// On trouve également une propriété calculée Albums qui réalise une projection de la collection précédente pour obtenir les albums, ainsi + /// qu'une méthode AddAlbum rajoutant une ligne dans la table d'association. + /// + [Table("Artistes")] + public class Artiste + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + public string Prénom + { + get; set; + } + public string Nom + { + get; set; + } + + public DateTime DateDeNaissance + { + get; set; + } + + public DateTime? DateDeMort + { + get; set; + } + + public virtual IEnumerable Albums + { + get + { + return AlbumsArtistes.Select(aa => aa.Album); + } + } + + public void AddAlbum(Album album) + { + AlbumsArtistes.Add(new AlbumArtiste() { Album = album, Artiste = this }); + } + + public virtual ICollection AlbumsArtistes { get; set; } = new List(); + } +} diff --git a/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/DbContextInitializer.cs b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/DbContextInitializer.cs new file mode 100644 index 0000000..aecbb64 --- /dev/null +++ b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/DbContextInitializer.cs @@ -0,0 +1,105 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; + +namespace ex_042_010_EF_CF_Many_to_Many +{ + /// + /// initialiseur de stratégies... + /// + public static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(AlbumArtisteDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Dictionary albums = new Dictionary() + { + ["kindOfBlue"] = new Album { Titre = "Kind of Blue", DateDeSortie = new DateTime(1959, 8, 17) }, + ["somethinElse"] = new Album { Titre = "Somethin' Else", DateDeSortie = new DateTime(1958, 8, 1) } + }; + Dictionary artistes = new Dictionary() + { + ["milesDavis"] = new Artiste { Prénom = "Miles", Nom = "Davis", DateDeNaissance = new DateTime(1926, 5, 26), DateDeMort = new DateTime(1991, 9, 28) }, + ["johnColtrane"] = new Artiste { Prénom = "John", Nom = "Coltrane", DateDeNaissance = new DateTime(1926, 9, 23), DateDeMort = new DateTime(1967, 7, 11) }, + ["julianAdderley"] = new Artiste { Prénom = "Julian", Nom = "Adderley", DateDeNaissance = new DateTime(1928, 9, 15), DateDeMort = new DateTime(1975, 8, 8) }, + ["billEvans"] = new Artiste { Prénom = "Bill", Nom = "Evans", DateDeNaissance = new DateTime(1929, 8, 16), DateDeMort = new DateTime(1980, 9, 15) }, + ["wyntonKelly"] = new Artiste { Prénom = "Wynton", Nom = "Kelly", DateDeNaissance = new DateTime(1931, 12, 2), DateDeMort = new DateTime(1971, 4, 12) }, + ["paulChambers"] = new Artiste { Prénom = "Paul", Nom = "Chambers", DateDeNaissance = new DateTime(1935, 4, 22), DateDeMort = new DateTime(1969, 1, 4) }, + ["jimmyCobb"] = new Artiste { Prénom = "Jimmy", Nom = "Cobb", DateDeNaissance = new DateTime(1929, 1, 20) }, + ["hankJones"] = new Artiste { Prénom = "Hank", Nom = "Jones", DateDeNaissance = new DateTime(1918, 7, 31), DateDeMort = new DateTime(2010, 5, 16) }, + ["samJones"] = new Artiste { Prénom = "Sam", Nom = "Jones", DateDeNaissance = new DateTime(1924, 11, 12), DateDeMort = new DateTime(1981, 12, 15) }, + ["artBlakey"] = new Artiste { Prénom = "Art", Nom = "Blakey", DateDeNaissance = new DateTime(1919, 10, 11), DateDeMort = new DateTime(1990, 10, 16) } + }; + + //les artistes qui jouent sur Kind Of Blue sont reliés à l'album + albums["kindOfBlue"].AddArtiste(artistes["milesDavis"]); + albums["kindOfBlue"].AddArtiste(artistes["johnColtrane"]); + albums["kindOfBlue"].AddArtiste(artistes["julianAdderley"]); + albums["kindOfBlue"].AddArtiste(artistes["billEvans"]); + albums["kindOfBlue"].AddArtiste(artistes["wyntonKelly"]); + albums["kindOfBlue"].AddArtiste(artistes["paulChambers"]); + albums["kindOfBlue"].AddArtiste(artistes["jimmyCobb"]); + + //les artistes qui jouent sur Somethin' Else sont reliés à l'album + + albums["somethinElse"].AddArtiste(artistes["julianAdderley"]); + albums["somethinElse"].AddArtiste(artistes["milesDavis"]); + albums["somethinElse"].AddArtiste(artistes["hankJones"]); + albums["somethinElse"].AddArtiste(artistes["samJones"]); + albums["somethinElse"].AddArtiste(artistes["artBlakey"]); + + + context.Albums.AddRange(albums.Values); + context.Artistes.AddRange(artistes.Values); + + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Program.cs b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Program.cs new file mode 100644 index 0000000..08e1c85 --- /dev/null +++ b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/Program.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using static System.Console; +using Microsoft.EntityFrameworkCore; + +namespace ex_042_010_EF_CF_Many_to_Many +{ + public class Program + { + /// + /// Cet exemple montre comment construire une relation many-many dans la base de données en utilisant les conventions de nommage Entity Framework. + /// + /// Aujourd'hui (21 octobre 2016), il n'est malheureusement toujours pas possible d'utiliser les annotations de données pour réaliser une opération many to many. + /// Cet exemple propose une solution pour s'en approcher, mais qui nécessite quand même de modifier AlbumArtisteDBEntities (méthode OnModelCreating) et surtout + /// de créer une classe supplémentaire qui sera mappée à une table d'association. + /// Je ne conseille donc pas vraiment cette solution qui nécessite la modification des classes du modèle. + /// + /// on utilise les données stubbées de DbContextInitializer + /// On affiche les Albums et les Artistes. + /// + /// Si vous ouvrez la base de données (via l'explorateur d'objets SQL Server), vous pourrez constater la création d'une table d'association. + /// + /// + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + try + { + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (AlbumArtisteDBEntities db = new AlbumArtisteDBEntities()) + { + //choix de la stratégie et remplissage avec des données stubbées + DbContextInitializer.Seed(db); + } + using (AlbumArtisteDBEntities db = new AlbumArtisteDBEntities()) + { + WriteLine("Albums : "); + foreach (var album in db.Albums.Include(a => a.AlbumsArtistes).ThenInclude(aa => aa.Artiste)) + { + WriteLine($"\t{album.UniqueId}: {album.Titre} (sorti le : {album.DateDeSortie.ToString("d")})"); + foreach (var artiste in album.Artistes) + { + WriteLine($"\t\t{artiste.Prénom} {artiste.Nom}"); + } + } + + WriteLine(); + + WriteLine("Artistes :"); + foreach (var artiste in db.Artistes.Include(a => a.AlbumsArtistes).ThenInclude(aa => aa.Album)) + { + var annéeDeMort = artiste.DateDeMort.HasValue ? $" - {artiste.DateDeMort.Value.Year}" : ""; + var titresAlbums = artiste.Albums.Aggregate(String.Empty, (albums, album) => albums + $"\"{album.Titre}\" "); + WriteLine($"\t{artiste.UniqueId}: {artiste.Prénom} {artiste.Nom} ({artiste.DateDeNaissance.Year}{annéeDeMort}) (albums: {titresAlbums})"); + } + + } + } + catch (NotImplementedException exception) + { + WriteLine(exception.Message); + } + catch (Exception) + { + WriteLine("Votre base de données n'existe pas. C'est peut-être la première fois que vous exécutez cet exemple."); + WriteLine("Pour créer la base de données, suivez les instructions suivantes (que vous retrouvez en commentaires dans la classe Program) :"); + WriteLine("Pour créer la base, ouvrez un invite de commandes et placez-vous dans le dossier de ce projet, ou bien,"); + WriteLine("- dans Visual Studio ouvrez la Console du Gestionnaire de package (Outils -> Gestionnaire de package NuGet -> Console du Gestionnaire de package),"); + WriteLine("- dans cette Console, vous devriez être dans le dossier de la solution, déplacez-vous dans celui du projet (ici : cd ex_042_010_EF_CF_Many_to_Many)"); + WriteLine("- tapez : dotnet restore (pour restaurer les packages .NET Core)"); + WriteLine("- tapez : dotnet ef migrations add MyFirstMigration"); + WriteLine(" note : vous pourrez détruire le dossier Migrations une fois la base créée"); + WriteLine("- tapez : dotnet ef database update"); + WriteLine(" Ceci génère la base de données en utilisant la migration, et en particulier votre classe DBContext et vos classes POCO."); + WriteLine("\nDans cet exemple, une base de données SQLServer est créée et en particulier la table Nounours.mdf"); + } + + ReadLine(); + } + } +} diff --git a/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/ex_042_010_EF_CF_Many_to_Many.csproj b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/ex_042_010_EF_CF_Many_to_Many.csproj new file mode 100644 index 0000000..c8053ba --- /dev/null +++ b/p07_Persistance/ex_042_010_EF_CF_Many_to_Many/ex_042_010_EF_CF_Many_to_Many.csproj @@ -0,0 +1,21 @@ + + + net6.0 + ex_042_010_EF_CF_Many_to_Many + Exe + ex_042_010_EF_CF_Many_to_Many + 6.0.6 + false + false + false + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Album.cs b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Album.cs new file mode 100644 index 0000000..a0a58d0 --- /dev/null +++ b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Album.cs @@ -0,0 +1,64 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Album.cs +// Author : Marc Chevaldonné +// Creation date : 2019-12-23 +// +// ======================================================================== + + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; + +namespace ex_042_011_EF_CF_Many_to_Many_FluentAPI +{ + /// + /// Album est une classe POCO, i.e. Plain Old CLR Object. + /// Elle a une relation many-many avec la classe Artiste via la propriété Artistes. + /// La clé primaire est générée lors de l'insertion en table. + /// + /// Aujourd'hui (21 octobre 2016), il n'est pas encore possible d'utiliser les annotations de données pour les relations many to many. + /// En conséquence, il faut créer une classe pour la table d'association. + /// Dans la classe Album, on trouve donc une propriété AlbumsArtistes, collection de AlbumArtiste (correspondant à la table d'association). + /// On trouve également une propriété calculée Artistes qui réalise une projection de la collection précédente pour obtenir les artistes, ainsi + /// qu'une méthode AddArtiste rajoutant une ligne dans la table d'association. + /// + public class Album + { + public Guid UniqueId + { + get; set; + } + + public string Titre + { + get; set; + } + + public DateTime DateDeSortie + { + get; set; + } + + public virtual IEnumerable Artistes + { + get + { + return AlbumsArtistes.Select(aa => aa.Artiste); + } + } + + public void AddArtiste(Artiste artiste) + { + AlbumsArtistes.Add(new AlbumArtiste() { Album = this, Artiste = artiste }); + } + + public virtual ICollection AlbumsArtistes { get; set; } = new List(); + } +} diff --git a/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/AlbumArtiste.cs b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/AlbumArtiste.cs new file mode 100644 index 0000000..b734113 --- /dev/null +++ b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/AlbumArtiste.cs @@ -0,0 +1,33 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AlbumArtiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace ex_042_011_EF_CF_Many_to_Many_FluentAPI +{ + /// + /// table permettant de réaliser la table d'association + /// + public class AlbumArtiste + { + /// + /// un album... + /// + public Album Album { get; set; } + /// + /// ...lié à un artiste + /// + public Artiste Artiste { get; set; } + } +} diff --git a/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/AlbumArtisteDBEntities.cs b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/AlbumArtisteDBEntities.cs new file mode 100644 index 0000000..b071e7b --- /dev/null +++ b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/AlbumArtisteDBEntities.cs @@ -0,0 +1,67 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AlbumArtisteDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_011_EF_CF_Many_to_Many_FluentAPI +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient deux DbSet pour permettre de réaliser des opérations CRUD sur les types T, ici Album et Artiste. + /// + public class AlbumArtisteDBEntities : DbContext + { + public virtual DbSet Artistes { get; set; } + public virtual DbSet Albums { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_011_EF_CF_Many_to_Many_FluentAPI.mdf;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + //création de la table Albums + modelBuilder.Entity().ToTable("Albums"); //nom de la table + modelBuilder.Entity().HasKey(a => a.UniqueId); //définition de la clé primaire + modelBuilder.Entity().Property(a => a.UniqueId) + .ValueGeneratedOnAdd(); //définition du mode de génération de la clé : génération à l'insertion + + //création de la table "Artistes" + modelBuilder.Entity().ToTable("Artistes"); // nom de la table + modelBuilder.Entity().HasKey(a => a.UniqueId); //définition de la clé primaire + modelBuilder.Entity().Property(a => a.UniqueId) + .ValueGeneratedOnAdd(); // définition du mode de génération de la clé : pas de génération automatique + + //ajoute deux shadow properties à la classe AlbumArtiste pour qu'elles soient utilisées comme clés étrangères + modelBuilder.Entity().Property("AlbumId"); + modelBuilder.Entity().Property("ArtisteId"); + + //crée une clé primaire à partir des deux propriétés précédentes + modelBuilder.Entity().HasKey("AlbumId", "ArtisteId"); + + //lie l'entité AlbumArtiste à l'entité Album + modelBuilder.Entity() + .HasOne(aa => aa.Album) + .WithMany(album => album.AlbumsArtistes) + .HasForeignKey("AlbumId"); + + //lie l'entité AlbumArtiste à l'entité Artiste + modelBuilder.Entity() + .HasOne(aa => aa.Artiste) + .WithMany(artiste => artiste.AlbumsArtistes) + .HasForeignKey("ArtisteId"); + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Artiste.cs b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Artiste.cs new file mode 100644 index 0000000..7e1b4c2 --- /dev/null +++ b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Artiste.cs @@ -0,0 +1,73 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Artiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; + +namespace ex_042_011_EF_CF_Many_to_Many_FluentAPI +{ + /// + /// Artiste est une classe POCO, i.e. Plain Old CLR Object. + /// Elle a une relation many-many avec la classe Artiste via la propriété Artistes. + /// La clé primaire est générée lors de l'insertion en table. + /// + /// Aujourd'hui (21 octobre 2016), il n'est pas encore possible d'utiliser les annotations de données pour les relations many to many. + /// En conséquence, il faut créer une classe pour la table d'association. + /// Dans la classe Artiste, on trouve donc une propriété AlbumsArtistes, collection de AlbumArtiste (correspondant à la table d'association). + /// On trouve également une propriété calculée Albums qui réalise une projection de la collection précédente pour obtenir les albums, ainsi + /// qu'une méthode AddAlbum rajoutant une ligne dans la table d'association. + /// + public class Artiste + { + public Guid UniqueId + { + get; set; + } + + public string Prénom + { + get; set; + } + public string Nom + { + get; set; + } + + public DateTime DateDeNaissance + { + get; set; + } + + public DateTime? DateDeMort + { + get; set; + } + + public virtual IEnumerable Albums + { + get + { + return AlbumsArtistes.Select(aa => aa.Album); + } + } + + public void AddAlbum(Album album) + { + AlbumsArtistes.Add(new AlbumArtiste() { Album = album, Artiste = this }); + } + + public virtual ICollection AlbumsArtistes { get; set; } = new List(); + } +} diff --git a/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/DbContextInitializer.cs b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/DbContextInitializer.cs new file mode 100644 index 0000000..a273e5b --- /dev/null +++ b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/DbContextInitializer.cs @@ -0,0 +1,105 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-21 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; + +namespace ex_042_011_EF_CF_Many_to_Many_FluentAPI +{ + /// + /// initialiseur de stratégies... + /// + public static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(AlbumArtisteDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Dictionary albums = new Dictionary() + { + ["kindOfBlue"] = new Album { Titre = "Kind of Blue", DateDeSortie = new DateTime(1959, 8, 17) }, + ["somethinElse"] = new Album { Titre = "Somethin' Else", DateDeSortie = new DateTime(1958, 8, 1) } + }; + Dictionary artistes = new Dictionary() + { + ["milesDavis"] = new Artiste { Prénom = "Miles", Nom = "Davis", DateDeNaissance = new DateTime(1926, 5, 26), DateDeMort = new DateTime(1991, 9, 28) }, + ["johnColtrane"] = new Artiste { Prénom = "John", Nom = "Coltrane", DateDeNaissance = new DateTime(1926, 9, 23), DateDeMort = new DateTime(1967, 7, 11) }, + ["julianAdderley"] = new Artiste { Prénom = "Julian", Nom = "Adderley", DateDeNaissance = new DateTime(1928, 9, 15), DateDeMort = new DateTime(1975, 8, 8) }, + ["billEvans"] = new Artiste { Prénom = "Bill", Nom = "Evans", DateDeNaissance = new DateTime(1929, 8, 16), DateDeMort = new DateTime(1980, 9, 15) }, + ["wyntonKelly"] = new Artiste { Prénom = "Wynton", Nom = "Kelly", DateDeNaissance = new DateTime(1931, 12, 2), DateDeMort = new DateTime(1971, 4, 12) }, + ["paulChambers"] = new Artiste { Prénom = "Paul", Nom = "Chambers", DateDeNaissance = new DateTime(1935, 4, 22), DateDeMort = new DateTime(1969, 1, 4) }, + ["jimmyCobb"] = new Artiste { Prénom = "Jimmy", Nom = "Cobb", DateDeNaissance = new DateTime(1929, 1, 20) }, + ["hankJones"] = new Artiste { Prénom = "Hank", Nom = "Jones", DateDeNaissance = new DateTime(1918, 7, 31), DateDeMort = new DateTime(2010, 5, 16) }, + ["samJones"] = new Artiste { Prénom = "Sam", Nom = "Jones", DateDeNaissance = new DateTime(1924, 11, 12), DateDeMort = new DateTime(1981, 12, 15) }, + ["artBlakey"] = new Artiste { Prénom = "Art", Nom = "Blakey", DateDeNaissance = new DateTime(1919, 10, 11), DateDeMort = new DateTime(1990, 10, 16) } + }; + + //les artistes qui jouent sur Kind Of Blue sont reliés à l'album + albums["kindOfBlue"].AddArtiste(artistes["milesDavis"]); + albums["kindOfBlue"].AddArtiste(artistes["johnColtrane"]); + albums["kindOfBlue"].AddArtiste(artistes["julianAdderley"]); + albums["kindOfBlue"].AddArtiste(artistes["billEvans"]); + albums["kindOfBlue"].AddArtiste(artistes["wyntonKelly"]); + albums["kindOfBlue"].AddArtiste(artistes["paulChambers"]); + albums["kindOfBlue"].AddArtiste(artistes["jimmyCobb"]); + + //les artistes qui jouent sur Somethin' Else sont reliés à l'album + + albums["somethinElse"].AddArtiste(artistes["julianAdderley"]); + albums["somethinElse"].AddArtiste(artistes["milesDavis"]); + albums["somethinElse"].AddArtiste(artistes["hankJones"]); + albums["somethinElse"].AddArtiste(artistes["samJones"]); + albums["somethinElse"].AddArtiste(artistes["artBlakey"]); + + + context.Albums.AddRange(albums.Values); + context.Artistes.AddRange(artistes.Values); + + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Program.cs b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Program.cs new file mode 100644 index 0000000..93eb1c2 --- /dev/null +++ b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/Program.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using static System.Console; +using Microsoft.EntityFrameworkCore; + +namespace ex_042_011_EF_CF_Many_to_Many_FluentAPI +{ + public class Program + { + /// + /// Cet exemple montre comment construire une relation many-many dans la base de données en utilisant les conventions de nommage Entity Framework. + /// + /// Aujourd'hui (21 octobre 2016), il n'est malheureusement toujours pas possible d'utiliser les annotations de données pour réaliser une opération many to many. + /// Cet exemple propose une solution pour s'en approcher, mais qui nécessite quand même de modifier AlbumArtisteDBEntities (méthode OnModelCreating) et surtout + /// de créer une classe supplémentaire qui sera mappée à une table d'association. + /// Je ne conseille donc pas vraiment cette solution qui nécessite la modification des classes du modèle. + /// + /// on utilise les données stubbées de DbContextInitializer + /// On affiche les Albums et les Artistes. + /// + /// Si vous ouvrez la base de données (via l'explorateur d'objets SQL Server), vous pourrez constater la création d'une table d'association. + /// + /// + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + try + { + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (AlbumArtisteDBEntities db = new AlbumArtisteDBEntities()) + { + //choix de la stratégie et remplissage avec des données stubbées + DbContextInitializer.Seed(db); + } + using (AlbumArtisteDBEntities db = new AlbumArtisteDBEntities()) + { + + WriteLine("Albums : "); + foreach (var album in db.Albums.Include(a => a.AlbumsArtistes) + .ThenInclude(aa => aa.Artiste)) + { + WriteLine($"\t{album.UniqueId}: {album.Titre} (sorti le : {album.DateDeSortie.ToString("d")})"); + foreach (var artiste in album.Artistes) + { + WriteLine($"\t\t{artiste.Prénom} {artiste.Nom}"); + } + } + + WriteLine(); + + WriteLine("Artistes :"); + foreach (var artiste in db.Artistes.Include(a => a.AlbumsArtistes) + .ThenInclude(aa => aa.Album)) + { + var annéeDeMort = artiste.DateDeMort.HasValue ? $" - {artiste.DateDeMort.Value.Year}" : ""; + var titresAlbums = artiste.Albums.Aggregate(String.Empty, (albums, album) => albums + $"\"{album.Titre}\" "); + WriteLine($"\t{artiste.UniqueId}: {artiste.Prénom} {artiste.Nom} ({artiste.DateDeNaissance.Year}{annéeDeMort}) (albums: {titresAlbums})"); + } + + } + } + catch (NotImplementedException exception) + { + WriteLine(exception.Message); + } + catch (Exception) + { + WriteLine("Votre base de données n'existe pas. C'est peut-être la première fois que vous exécutez cet exemple."); + WriteLine("Pour créer la base de données, suivez les instructions suivantes (que vous retrouvez en commentaires dans la classe Program) :"); + WriteLine("Pour créer la base, ouvrez un invite de commandes et placez-vous dans le dossier de ce projet, ou bien,"); + WriteLine("- dans Visual Studio ouvrez la Console du Gestionnaire de package (Outils -> Gestionnaire de package NuGet -> Console du Gestionnaire de package),"); + WriteLine("- dans cette Console, vous devriez être dans le dossier de la solution, déplacez-vous dans celui du projet (ici : cd ex_042_010_EF_CF_Many_to_Many)"); + WriteLine("- tapez : dotnet restore (pour restaurer les packages .NET Core)"); + WriteLine("- tapez : dotnet ef migrations add MyFirstMigration"); + WriteLine(" note : vous pourrez détruire le dossier Migrations une fois la base créée"); + WriteLine("- tapez : dotnet ef database update"); + WriteLine(" Ceci génère la base de données en utilisant la migration, et en particulier votre classe DBContext et vos classes POCO."); + WriteLine("\nDans cet exemple, une base de données SQLServer est créée et en particulier la table Nounours.mdf"); + } + + ReadLine(); + } + } +} diff --git a/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/ex_042_011_EF_CF_Many_to_Many_FluentAPI.csproj b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/ex_042_011_EF_CF_Many_to_Many_FluentAPI.csproj new file mode 100644 index 0000000..7212ef3 --- /dev/null +++ b/p07_Persistance/ex_042_011_EF_CF_Many_to_Many_FluentAPI/ex_042_011_EF_CF_Many_to_Many_FluentAPI.csproj @@ -0,0 +1,15 @@ + + + + Exe + net6.0 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/DbContextInitializer.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/DbContextInitializer.cs new file mode 100644 index 0000000..63a6eca --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/DbContextInitializer.cs @@ -0,0 +1,94 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-01 +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; + +namespace ex_042_012_EF_CF_Dictionary +{ + /// + /// initialiseur de stratégies... + /// + public static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(NounoursDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Nounours[] lesNounours; + LitEntity[] lesLits; + List lesScores = new List(); + + //données stubbées + //simulation de données en utilisant les types du Model + Nounours chewie = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 }; + Nounours yoda = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 }; + Nounours ewok = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 }; + Nounours beluga = new Nounours { Nom = "Beluga", DateDeNaissance = new DateTime(2012, 07, 29), NbPoils = 0 }; + Nounours singe = new Nounours { Nom = "Singe", DateDeNaissance = new DateTime(2009, 08, 09), NbPoils = 1345 }; + Nounours girafe = new Nounours { Nom = "Girafe", DateDeNaissance = new DateTime(2007, 11, 02), NbPoils = 567 }; + lesNounours = new Nounours[] { chewie, yoda, ewok, beluga, singe, girafe }; + + LitEntity litDeLuke = new LitEntity() { Propriétaire = "Luke" }; + litDeLuke[chewie] = 100; + litDeLuke[yoda] = 200; + litDeLuke[ewok] = 1; + + LitEntity monLit = new LitEntity() { Propriétaire = "Moi" }; + monLit[beluga] = 10; + monLit[singe] = 100; + monLit[girafe] = 1000; + + lesLits = new LitEntity[] { litDeLuke, monLit }; + + //***************** + + context.AddAll(lesLits, lesNounours); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/DictionaryItem.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/DictionaryItem.cs new file mode 100644 index 0000000..6910711 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/DictionaryItem.cs @@ -0,0 +1,48 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DictionaryItem.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-01 +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_012_EF_CF_Dictionary +{ + /// + /// classe de base permettant de transformer un dictionnaire Dictionary en + /// ICollection> permettant la liaison avec Entity Framwork. + /// Dans la classe Score, TKey est de type Nounours et TValue est de type int. + /// La propriété Key permet donc de réaliser la relation one to one avec NounoursEx. + /// La propriété Value permet d'obtenir la valeur associée (ici le score entier). + /// + /// + /// + public class Item + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + public TKey Key + { + get; + set; + } + + public TValue Value + { + get; set; + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/LitEntity.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/LitEntity.cs new file mode 100644 index 0000000..9e2a829 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/LitEntity.cs @@ -0,0 +1,79 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : LitEntity.cs +// Author : Marc Chevaldonné +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; + +namespace ex_042_012_EF_CF_Dictionary +{ + [Table("Lits")] + public class LitEntity : ILit + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + public string Propriétaire + { + get; set; + } + + /// + /// remplace le dictionnaire : on utilise une collection de Scores afin d'établir une relation one to many entre + /// LitEx et Score + /// + internal virtual ICollection mScores + { + get; + set; + } = new List(); + + public int this[INounours nounours] + { + get + { + var score = mScores.SingleOrDefault(sc => sc.Key.Equals(nounours)); + return score != null ? score.Value : 0; + } + set + { + var score = mScores.SingleOrDefault(sc => sc.Key.Equals(nounours)); + if (score != null) + { + score.Value = value; + } + else + { + var n = nounours as Nounours; + if (n == null) throw new InvalidCastException("nounours should be of type Nounours"); + + Score newScore = new Score() + { + Key = n, + Value = value, + Lit = this + }; + mScores.Add(newScore); + } + } + } + + public ReadOnlyDictionary Scores => + new ReadOnlyDictionary(mScores.ToDictionary(kvp => kvp.Key as INounours, kvp => kvp.Value)); + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/NounoursDbEntities.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/NounoursDbEntities.cs new file mode 100644 index 0000000..aac8155 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/NounoursDbEntities.cs @@ -0,0 +1,82 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : LitEntity.cs +// Author : Marc Chevaldonné +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; + +namespace ex_042_012_EF_CF_Dictionary +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient deux DbSet pour permettre de réaliser des opérations CRUD sur les types T, ici Nounours et CarnetDeSante. + /// + public class NounoursDBEntities : DbContext + { + public virtual DbSet NounoursSet { get; set; } + public virtual DbSet LitsSet { get; set; } + public virtual DbSet ScoresSet { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.EnableSensitiveDataLogging(); + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_012_EF_CF_Dictionary.Nounours.mdf;Trusted_Connection=True;"); + } + + /// + /// méthode appelée lors de la création du modèle. + /// + /// + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + //création de la table TableNounours + modelBuilder.Entity().ToTable("Nounours"); //nom de la table + modelBuilder.Entity().HasKey(n => n.UniqueId); //définition de la clé primaire + modelBuilder.Entity().Property(n => n.UniqueId) + .ValueGeneratedOnAdd() ; + modelBuilder.Entity().Property(n => n.Nom).IsRequired() + .HasMaxLength(256); //définition de la colonne Nom + modelBuilder.Entity().Property(n => n.DateDeNaissance).HasColumnName("Naissance"); //changement du nom de la colonne Naissance + //note : la colonne NbPoils n'est pas changée : utilisation des conventions EF + + modelBuilder.Entity().Property(n => n.UniqueId).ValueGeneratedOnAdd(); + + //on crée une propriété fantôme (shadow property) pour l'entity Score qu'on utilisera comme clé étrangère (foreign key) + // En effet, j'ai pris le cas où nous décidons d'utiliser une classe existante pour laquelle aucune clé étrangère n'a été prévue. + // Il me semblait donc logique qu'on cherche à l'utiliser sans qu'elle soit dans le modèle + modelBuilder.Entity().Property("ScoreId"); + + //on précise qu'il y a une relation entre Lit et Score + modelBuilder.Entity().HasMany(l => l.mScores) // on dit que le lit a plusieurs scores + .WithOne(s => s.Lit) // et que chaque score a un lit + .HasForeignKey("ScoreId"); //on utilise la clé étrangère fantôme créée précédemment + + base.OnModelCreating(modelBuilder); + } + + List lesScores = new List(); + + /// + /// ajoute des lits et des nounours à la base + /// + /// + /// + public void AddAll(IEnumerable lesLits, IEnumerable lesNounours) + { + //met à jour les tables + NounoursSet.AddRange(lesNounours); + LitsSet.AddRange(lesLits); + ScoresSet.AddRange(lesScores); + + SaveChanges(); + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/Score.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/Score.cs new file mode 100644 index 0000000..c35a586 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/DbEntities/Score.cs @@ -0,0 +1,29 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Score.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-01 +// Last Modified : 2019-12-25 +// +// ======================================================================== + +namespace ex_042_012_EF_CF_Dictionary +{ + /// + /// classe permettant de réaliser une relation one to many avec Lit, et one to one avec Nounours + /// Elle remplace le KeyValuePair, type des éléments du dictionaire Scores de Lit. + /// + public class Score : Item + { + /// + /// lien vers le LitEx pour la liaison one to many avec LitEx + /// + public LitEntity Lit + { + get; set; + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/ILit.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/ILit.cs new file mode 100644 index 0000000..5df5b94 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/ILit.cs @@ -0,0 +1,40 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : ILit.cs +// Author : Marc Chevaldonné +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using System; +using System.Collections.ObjectModel; + +namespace ex_042_012_EF_CF_Dictionary +{ + public interface ILit + { + Guid UniqueId + { + get; set; + } + + string Propriétaire + { + get; set; + } + + ReadOnlyDictionary Scores + { + get; + } + + int this[INounours nounours] + { + get; + set; + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/INounours.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/INounours.cs new file mode 100644 index 0000000..d1eb5aa --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/INounours.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : INounours.cs +// Author : Marc Chevaldonné +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using System; + +namespace ex_042_012_EF_CF_Dictionary +{ + public interface INounours + { + Guid UniqueId + { + get; set; + } + + string Nom + { + get; + set; + } + + DateTime DateDeNaissance + { + get; + set; + } + + int NbPoils + { + get; + set; + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/INounoursEqualityComparer.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/INounoursEqualityComparer.cs new file mode 100644 index 0000000..60b9503 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/INounoursEqualityComparer.cs @@ -0,0 +1,28 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : INounoursEqualityComparer.cs +// Author : Marc Chevaldonné +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using System.Collections.Generic; + +namespace ex_042_012_EF_CF_Dictionary.Model +{ + class INounoursEqualityComparer : EqualityComparer + { + public override bool Equals(INounours x, INounours y) + { + return x.Nom == y.Nom && x.DateDeNaissance == y.DateDeNaissance; + } + + public override int GetHashCode(INounours obj) + { + return obj.GetHashCode(); + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/Lit.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/Lit.cs new file mode 100644 index 0000000..a9f4cb5 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/Lit.cs @@ -0,0 +1,66 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Lit.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-01 +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace ex_042_012_EF_CF_Dictionary +{ + public class Lit : ILit + { + public Guid UniqueId + { + get; set; + } + + public string Propriétaire + { + get; set; + } + + public Lit() + { + Scores = new ReadOnlyDictionary(mScores); + } + + /// + /// dictionnaire de Nounours (un score entier est associé à chaque nounours) + /// + private Dictionary mScores { get; set; } = new Dictionary(); + + /// + /// permet d'accéder en lecture seule au dictionnaie de scores + /// + public ReadOnlyDictionary Scores + { + get; private set; + } + + /// + /// un indexeur pour pouvoir lire et modifier le score d'un Nounours + /// + /// + /// + public int this[INounours nounours] + { + get + { + return mScores[nounours]; + } + set + { + mScores[nounours] = value; + } + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/Nounours.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/Nounours.cs new file mode 100644 index 0000000..590330e --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Model/Nounours.cs @@ -0,0 +1,96 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-01 +// Last Modified : 2019-12-25 +// +// ======================================================================== + +using System; + +namespace ex_042_012_EF_CF_Dictionary +{ + /// + /// Nounours est une classe POCO, i.e. Plain Old CLR Object. + /// + public class Nounours : INounours + { + public Guid UniqueId + { + get; set; + } + + public string Nom + { + get; + set; + } + + public DateTime DateDeNaissance + { + get; + set; + } + + public int NbPoils + { + get; + set; + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{UniqueId}: {Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/Program.cs b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Program.cs new file mode 100644 index 0000000..9590478 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/Program.cs @@ -0,0 +1,72 @@ +// ======================================================================== +// +// Copyright (C) 2019-2020 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-01 +// Mise à jour : 2019-12-25 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using static System.Console; + +namespace ex_042_012_EF_CF_Dictionary +{ + /// + /// L'utilisation de dictionnaires est "déconseillée" lors de l'utilisation d'Entity Framework par les utilisateurs car ils ne sont pas gérés par EF comme une relation entre entités. + /// Personnellement, je n'aime pas que le choix d'une technologie apporte des contraintes sur mon modèle. + /// Voici donc une proposition de solution quant à l'utilisation de dictionnaires dans votre modèle. + /// Son avantage est de ne pas vous obliger à modifier votre modèle. Pour cela : + /// 1) j'utilise deux interfaces publiques : ILit et INounours qui doivent être utilisées le plus possible en lieu et place des classes qui les implémentent. + /// 2) Nounours implémente INounours et comme c'est une classe simple (sans collection ni dictionnaire, ni lien direct avec une autre classe), elle sera également utilisée + /// comme entité via EF ; mais comme je n'ai pas voulu polluer mon modèle avec des annotations EF, j'utilise soit les conventions de nommage, soit la fluent API (cf. NounoursDbEntities.cs) + /// 3) Lit implémente ILit avec un dictionnaire, mais on n'accède jamais au dictionnaire directement (imposé par ILit). On peut lire et modifier les élements via le ReadOnlyDictionary, + /// et l'indexeur. Lit ne peut pas être utilisé comme entité à cause du dictionnaire. Je crée donc une autre classe LitEntity qui implémente ILit et permet le lien avec EF. + /// Ici, le dictionnaire est remplacé par une collection de Score qui implémente Item. Une projection permet de la transformer en ReadOnlyDictionary, et l'indexeur accède aux éléments de la collection. + /// Puisque LitEntity est écrite pour le lien avec EF, je peux me permettre d'utiliser les annotations et la Fluent API pour le lien avec les scores. + /// En conséquence, le dictionnaire ReadOnlyDictionary dans ILit est transformé en deux relations : + /// a) une relation one to many entre Lit et une nouvelle classe Score + /// b) une relation entre Score et Nounours + /// De plus, Score contient non seulement le Nounours qui servait de clé dans le dictionnaire, mais également la valeur qui était associée à cette clé. + /// 4) la classe NounoursDBEntities (le DBContext) possède une méthode AddAll permettant d'ajouter dans la base des nounours et des lits. + /// + /// Pour finir, j'ai cherché à mettre en oeuvre une solution plus élégante et plus rapide à écrire avec Entity Framework 7. Celle-ci se base sur l'utilisation des shadow properties et de la réécriture des méthodes + /// du DbContext pour permettre la transformation du dictionnaire en collections. Malheureusement, cette solution ne peut pas être utilisée aujourd'hui car les shadow properties ne peuvent pas être des collections + /// dans Entity Framework Core. Espérons qu'il sera possible dans la prochaine version d'EF Core d'utiliser des shadow properties de type collections, ou mieux, que les dictionnaires soient gérés par EF Core et + /// directement transformés en relations ! + /// + public class Program + { + public static void Main(string[] args) + { + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (NounoursDBEntities db = new NounoursDBEntities()) + { + //choix de la stratégie et remplissage avec des données stubbées + DbContextInitializer.Seed(db); + } + + using (NounoursDBEntities db = new NounoursDBEntities()) + { + WriteLine("les nounours : "); + foreach (var n in db.NounoursSet) + { + WriteLine($"\t{n}"); + } + + WriteLine("les lits : "); + foreach (var l in db.LitsSet.Include(l => l.mScores)) + { + WriteLine($"\t{l.Propriétaire}"); + foreach (var kvp in l.Scores) + { + WriteLine($"\t\t{kvp.Key.Nom}: {kvp.Value}"); + } + } + } + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Dictionary/ex_042_012_EF_CF_Dictionary.csproj b/p07_Persistance/ex_042_012_EF_CF_Dictionary/ex_042_012_EF_CF_Dictionary.csproj new file mode 100644 index 0000000..53a884e --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Dictionary/ex_042_012_EF_CF_Dictionary.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_012_EF_CF_Dictionary + Exe + ex_042_012_EF_CF_Dictionary + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumArtiste.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumArtiste.cs new file mode 100644 index 0000000..1068fb7 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumArtiste.cs @@ -0,0 +1,28 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AlbumArtiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// table permettant de réaliser la table d'association + /// + public class AlbumArtiste + { + /// + /// un album... + /// + public AlbumEF Album { get; set; } + /// + /// ...lié à un artiste + /// + public ArtisteEF Artiste { get; set; } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumArtisteDBEntities.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumArtisteDBEntities.cs new file mode 100644 index 0000000..86208dc --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumArtisteDBEntities.cs @@ -0,0 +1,78 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AlbumArtisteDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient deux DbSet pour permettre de réaliser des opérations CRUD sur les types T, ici Album et Artiste. + /// + public class AlbumArtisteDBEntities : DbContext + { + public virtual DbSet Artistes { get; set; } + public virtual DbSet Albums { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_012_EF_CF_Many_to_Many_procurators.mdf;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + //création de la table Albums + modelBuilder.Entity().ToTable("Albums"); //nom de la table + modelBuilder.Entity().HasKey(a => a.UniqueId); //définition de la clé primaire + modelBuilder.Entity().Property(a => a.UniqueId) + .ValueGeneratedOnAdd(); //définition du mode de génération de la clé : génération à l'insertion + + //création de la table "Artistes" + modelBuilder.Entity().ToTable("Artistes"); // nom de la table + modelBuilder.Entity().HasKey(a => a.UniqueId); //définition de la clé primaire + modelBuilder.Entity().Property(a => a.UniqueId) + .ValueGeneratedOnAdd(); // définition du mode de génération de la clé : pas de génération automatique + + //on demande au modelBuilder d'ignorer les types Album et Artiste dans la création des entities + modelBuilder.Ignore(typeof(Album)); + modelBuilder.Ignore(typeof(Artiste)); + + + //ajoute deux shadow properties à la classe AlbumArtiste pour qu'elles soient utilisées comme clés étrangères + modelBuilder.Entity().Property("AlbumId"); + modelBuilder.Entity().Property("ArtisteId"); + //ajoute les mêmes aux entités AlbumEF et ArtisteEF + //modelBuilder.Entity().Property("AlbumId"); + //modelBuilder.Entity().Property("ArtisteId"); + + modelBuilder.Entity().Ignore(a => a.Albums); + modelBuilder.Entity().Ignore(a => a.Artistes); + + //crée une clé primaire à partir des deux propriétés précédentes + modelBuilder.Entity().HasKey("AlbumId", "ArtisteId"); + + //lie l'entité AlbumArtiste à l'entité Album + modelBuilder.Entity() + .HasOne(aa => aa.Album) + .WithMany(album => album.AlbumsArtistes) + .HasForeignKey("AlbumId"); + + //lie l'entité AlbumArtiste à l'entité Artiste + modelBuilder.Entity() + .HasOne(aa => aa.Artiste) + .WithMany(artiste => artiste.ArtistesAlbums) + .HasForeignKey("ArtisteId"); + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumEF.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumEF.cs new file mode 100644 index 0000000..c2699e4 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/AlbumEF.cs @@ -0,0 +1,36 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : AlbumEF.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// procurateur pour la classe Album + /// + public class AlbumEF : Album + { + /// + /// collection d'AlbumArtiste pour le lien avec la table d'association + /// + public ICollection AlbumsArtistes { get; set; } = new List(); + + public new ICollection Artistes + { + get + { + return AlbumsArtistes.Select(aa => aa.Artiste).ToList(); + } + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/ArtisteEF.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/ArtisteEF.cs new file mode 100644 index 0000000..7a61e77 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/ArtisteEF.cs @@ -0,0 +1,33 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : ArtisteEF.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// procurateur pour la classe Artiste + /// + public class ArtisteEF : Artiste + { + public new ICollection Albums + { + get + { + return ArtistesAlbums.Select(aa => aa.Album).ToList(); + } + } + + public ICollection ArtistesAlbums { get; set; } = new List(); + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/DbContextInitializer.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/DbContextInitializer.cs new file mode 100644 index 0000000..ee5a8fc --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/DbEntities/DbContextInitializer.cs @@ -0,0 +1,135 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// initialiseur de stratégies... + /// + public static class DbContextInitializer + { + //quelques dictionnaires pour aller plus vite dans la création du stub + static Dictionary albums; + static Dictionary artistes; + static Dictionary albumsEF; + static Dictionary artistesEF; + + /// + /// ajoute un couple album-artiste au context + /// + /// + /// + /// + static void AddArtisteAlbum(AlbumArtisteDBEntities context, string album, string artiste) + { + //met à jour les liens entre album et artiste + //albums[album].Artistes.Add(artistes[artiste]); + //artistes[artiste].Albums.Add(albums[album]); + + //récupère les procurateurs sur les album et artiste concernés + AlbumEF albumEF = albumsEF[album]; + ArtisteEF artisteEF = artistesEF[artiste]; + //création d'une entité albumartiste pour la table d'association + AlbumArtiste aa = new AlbumArtiste() { Album = albumEF, Artiste = artisteEF }; + //mise à jour des tables + albumEF.AlbumsArtistes.Add(aa); + artisteEF.ArtistesAlbums.Add(aa); + context.Albums.Add(albumEF); + context.Artistes.Add(artisteEF); + } + + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(AlbumArtisteDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + albumsEF = new Dictionary() + { + ["kindOfBlue"] = new AlbumEF { Titre = "Kind of Blue", DateDeSortie = new DateTime(1959, 8, 17) }, + ["somethinElse"] = new AlbumEF { Titre = "Somethin' Else", DateDeSortie = new DateTime(1958, 8, 1) } + }; + artistesEF = new Dictionary() + { + ["milesDavis"] = new ArtisteEF { Prénom = "Miles", Nom = "Davis", DateDeNaissance = new DateTime(1926, 5, 26), DateDeMort = new DateTime(1991, 9, 28) }, + ["johnColtrane"] = new ArtisteEF { Prénom = "John", Nom = "Coltrane", DateDeNaissance = new DateTime(1926, 9, 23), DateDeMort = new DateTime(1967, 7, 11) }, + ["julianAdderley"] = new ArtisteEF { Prénom = "Julian", Nom = "Adderley", DateDeNaissance = new DateTime(1928, 9, 15), DateDeMort = new DateTime(1975, 8, 8) }, + ["billEvans"] = new ArtisteEF { Prénom = "Bill", Nom = "Evans", DateDeNaissance = new DateTime(1929, 8, 16), DateDeMort = new DateTime(1980, 9, 15) }, + ["wyntonKelly"] = new ArtisteEF { Prénom = "Wynton", Nom = "Kelly", DateDeNaissance = new DateTime(1931, 12, 2), DateDeMort = new DateTime(1971, 4, 12) }, + ["paulChambers"] = new ArtisteEF { Prénom = "Paul", Nom = "Chambers", DateDeNaissance = new DateTime(1935, 4, 22), DateDeMort = new DateTime(1969, 1, 4) }, + ["jimmyCobb"] = new ArtisteEF { Prénom = "Jimmy", Nom = "Cobb", DateDeNaissance = new DateTime(1929, 1, 20) }, + ["hankJones"] = new ArtisteEF { Prénom = "Hank", Nom = "Jones", DateDeNaissance = new DateTime(1918, 7, 31), DateDeMort = new DateTime(2010, 5, 16) }, + ["samJones"] = new ArtisteEF { Prénom = "Sam", Nom = "Jones", DateDeNaissance = new DateTime(1924, 11, 12), DateDeMort = new DateTime(1981, 12, 15) }, + ["artBlakey"] = new ArtisteEF { Prénom = "Art", Nom = "Blakey", DateDeNaissance = new DateTime(1919, 10, 11), DateDeMort = new DateTime(1990, 10, 16) } + }; + + //albumsEF = albums.ToDictionary(kvp => kvp.Key, kvp => new AlbumEF(kvp.Value)); + //artistesEF = artistes.ToDictionary(kvp => kvp.Key, kvp => new ArtisteEF(kvp.Value)); + + //les artistes qui jouent sur Kind Of Blue sont reliés à l'album + AddArtisteAlbum(context, "kindOfBlue", "milesDavis"); + AddArtisteAlbum(context, "kindOfBlue", "johnColtrane"); + AddArtisteAlbum(context, "kindOfBlue", "julianAdderley"); + AddArtisteAlbum(context, "kindOfBlue", "billEvans"); + AddArtisteAlbum(context, "kindOfBlue", "wyntonKelly"); + AddArtisteAlbum(context, "kindOfBlue", "paulChambers"); + AddArtisteAlbum(context, "kindOfBlue", "jimmyCobb"); + + //les artistes qui jouent sur Somethin' Else sont reliés à l'album + AddArtisteAlbum(context, "somethinElse", "julianAdderley"); + AddArtisteAlbum(context, "somethinElse", "milesDavis"); + AddArtisteAlbum(context, "somethinElse", "hankJones"); + AddArtisteAlbum(context, "somethinElse", "samJones"); + AddArtisteAlbum(context, "somethinElse", "artBlakey"); + + context.SaveChanges(); + + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/Album.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/Album.cs new file mode 100644 index 0000000..47fe514 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/Album.cs @@ -0,0 +1,51 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Album.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + + +using System; +using System.Collections.Generic; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// Album est une classe POCO, i.e. Plain Old CLR Object. + /// Elle a une relation many-many avec la classe Artiste via la propriété Artistes. + /// La clé primaire est générée lors de l'insertion en table. + /// + /// Aujourd'hui (21 octobre 2016), il n'est pas encore possible dde mapper deux classes POCO avec la Fluent API sans passer par une entité avec une table d'association. + /// En conséquence, il faut créer une classe pour la table d'association. + /// Mais dans cet exemple, je ne souhaite pas modifier mon Model pour faire plaisir à Entity Framework, je le laisse donc tel quel... + /// + public class Album : IAlbum + { + public Album() + { + + } + public Guid UniqueId + { + get; set; + } + + public string Titre + { + get; set; + } + + public DateTime DateDeSortie + { + get; set; + } + + public ICollection Artistes { get; set; } = new List(); + } + +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/Artiste.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/Artiste.cs new file mode 100644 index 0000000..86d04fc --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/Artiste.cs @@ -0,0 +1,61 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Artiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// Artiste est une classe POCO, i.e. Plain Old CLR Object. + /// Elle a une relation many-many avec la classe Album via la propriété Albums. + /// La clé primaire est générée lors de l'insertion en table. + /// + /// + /// Aujourd'hui (21 octobre 2016), il n'est pas encore possible dde mapper deux classes POCO avec la Fluent API sans passer par une entité avec une table d'association. + /// En conséquence, il faut créer une classe pour la table d'association. + /// Mais dans cet exemple, je ne souhaite pas modifier mon Model pour faire plaisir à Entity Framework, je le laisse donc tel quel. + /// + public class Artiste : IArtiste + { + public Guid UniqueId + { + get; set; + } + + public string Prénom + { + get; set; + } + public string Nom + { + get; set; + } + + public DateTime DateDeNaissance + { + get; set; + } + + public DateTime? DateDeMort + { + get; set; + } + + public ICollection Albums { get; set; } = new List(); + } + + +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/IAlbum.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/IAlbum.cs new file mode 100644 index 0000000..2594a36 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/IAlbum.cs @@ -0,0 +1,27 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : IAlbum.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// façade immuable et couche abstraite commune pour le Model et le procurateur + /// + public interface IAlbum + { + Guid UniqueId { get; } + string Titre { get; } + DateTime DateDeSortie { get; } + ICollection Artistes { get; } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/IArtiste.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/IArtiste.cs new file mode 100644 index 0000000..d62c9b5 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Model/IArtiste.cs @@ -0,0 +1,48 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : IArtiste.cs +// Author : Marc Chevaldonné +// Creation date : 2016-10-23 +// +// ======================================================================== + +using System; +using System.Collections.Generic; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + /// + /// façade immuable et couche abstraite commune pour le Model et le procurateur + /// + public interface IArtiste + { + Guid UniqueId + { + get; + } + + string Prénom + { + get; + } + string Nom + { + get; + } + + DateTime DateDeNaissance + { + get; + } + + DateTime? DateDeMort + { + get; + } + + ICollection Albums { get; } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Program.cs b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Program.cs new file mode 100644 index 0000000..5320a8e --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/Program.cs @@ -0,0 +1,107 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using static System.Console; + +namespace ex_042_012_EF_CF_Many_to_Many_procurators +{ + public class Program + { + /// + /// Cet exemple montre comment construire une relation many-many dans la base de données en utilisant la Fluent API d'Entity Framework. + /// + /// Aujourd'hui (21 octobre 2016), il n'est malheureusement toujours pas possible de créer une table d'association automatiquement à partir de deux classes en relation many to many, + /// sans créer à la main une classe pour la table d'association. + /// + /// En attendant que cela soit mis en oeuvre par Microsoft (bientôt espérons-le...), cet exemple propose une solution pour permettre d'utiliser un modèle, sans le modifier, et sans qu'il soit explicitement lié aux tables. + /// Nous avons donc ici un Model (dossier Model) avec : + /// - une classe Album et sa façade immuable IAlbum, + /// - une classe Artiste et sa façade immuable IArtiste, + /// - la classe Album possède une collection d'Artistes, + /// - la classe Artiste possède une collection d'Albums. + /// + /// Dans le dossier DbEntities, il y a la mise en place d'un procurateur pour la classe Album (AlbumEF) et pour la classe Artiste (ArtisteEF), + /// qui sont en liaison many to many en utilisant l'entité AlbumArtiste, c'est-à-dire que : + /// - AlbumEF possède une collection d'AlbumArtiste, + /// - ArtisteEF possède une collection d'AlbumArtiste. + /// + /// La classe AlbumArtisteDBEntites crée le modèle et les tables. + /// + /// La classe DbContextInitializer remplit les tables avec des données stubbées. + /// + /// Je conseille plus cette solution que la précédente, car elle n'oblige pas à modifier les classes du modèle. Néanmoins, elle est assez lourde à mettre en oeuvre. + /// + /// Si vous ouvrez la base de données (via l'explorateur d'objets SQL Server), vous pourrez constater la création d'une table d'association. + /// + /// + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + try + { + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (AlbumArtisteDBEntities db = new AlbumArtisteDBEntities()) + { + //choix de la stratégie et remplissage avec des données stubbées + DbContextInitializer.Seed(db); + } + using (AlbumArtisteDBEntities db = new AlbumArtisteDBEntities()) + { + + WriteLine("Albums : "); + foreach (var album in db.Albums.Include(a => a.AlbumsArtistes).ThenInclude(aa => aa.Artiste)) + { + WriteLine($"\t{album.UniqueId}: {album.Titre} (sorti le : {album.DateDeSortie.ToString("d")})\n"); + foreach (var artiste in album.Artistes) + { + WriteLine($"\t\t{artiste.Prénom} {artiste.Nom}"); + } + } + + WriteLine(); + + WriteLine("Artistes :"); + foreach (var artiste in db.Artistes.Include(a => a.ArtistesAlbums).ThenInclude(aa => aa.Album)) + { + var annéeDeMort = artiste.DateDeMort.HasValue ? $" - {artiste.DateDeMort.Value.Year}" : ""; + var titresAlbums = artiste.Albums.Aggregate(String.Empty, (albums, album) => albums + $"\"{album.Titre}\" "); + WriteLine($"\t{artiste.UniqueId}: {artiste.Prénom} {artiste.Nom} ({artiste.DateDeNaissance.Year}{annéeDeMort}) (albums: {titresAlbums})"); + } + + //WriteLine("Albums : "); + //foreach (var album in db.Albums.Include(a => a.AlbumsArtistes)) + //{ + // WriteLine($"\t{album.UniqueId}: {album.Titre} (sorti le : {album.DateDeSortie.ToString("d")})"); + // foreach (var artiste in album.Artistes) + // { + // WriteLine($"\t\t{artiste.Prénom} {artiste.Nom}"); + // } + //} + + } + } + catch (NotImplementedException exception) + { + WriteLine(exception.Message); + } + catch (Exception e) + { + WriteLine("Votre base de données n'existe pas. C'est peut-être la première fois que vous exécutez cet exemple."); + WriteLine("Pour créer la base de données, suivez les instructions suivantes (que vous retrouvez en commentaires dans la classe Program) :"); + WriteLine("Pour créer la base, ouvrez un invite de commandes et placez-vous dans le dossier de ce projet, ou bien,"); + WriteLine("- dans Visual Studio ouvrez la Console du Gestionnaire de package (Outils -> Gestionnaire de package NuGet -> Console du Gestionnaire de package),"); + WriteLine("- dans cette Console, vous devriez être dans le dossier de la solution, déplacez-vous dans celui du projet (ici : cd ex_042_011_EF_CF_Many_to_Many_FluentAPI)"); + WriteLine("- tapez : dotnet restore (pour restaurer les packages .NET Core)"); + WriteLine("- tapez : dotnet ef migrations add MyFirstMigration"); + WriteLine(" note : vous pourrez détruire le dossier Migrations une fois la base créée"); + WriteLine("- tapez : dotnet ef database update"); + WriteLine(" Ceci génère la base de données en utilisant la migration, et en particulier votre classe DBContext et vos classes POCO."); + } + + ReadLine(); + } + } +} diff --git a/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/ex_042_012_EF_CF_Many_to_Many_procurators.csproj b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/ex_042_012_EF_CF_Many_to_Many_procurators.csproj new file mode 100644 index 0000000..ae325e2 --- /dev/null +++ b/p07_Persistance/ex_042_012_EF_CF_Many_to_Many_procurators/ex_042_012_EF_CF_Many_to_Many_procurators.csproj @@ -0,0 +1,21 @@ + + + net6.0 + ex_042_012_EF_CF_Many_to_Many_procurators + Exe + ex_042_012_EF_CF_Many_to_Many_procurators + 6.0.6 + false + false + false + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_013_EF_CF_TPT_Inheritance/Program.cs b/p07_Persistance/ex_042_013_EF_CF_TPT_Inheritance/Program.cs new file mode 100644 index 0000000..2ba5e81 --- /dev/null +++ b/p07_Persistance/ex_042_013_EF_CF_TPT_Inheritance/Program.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-07 +// +// ======================================================================== + +using static System.Console; + +namespace ex_042_013_EF_CF_TPT_Inheritance +{ + public class Program + { + /// + /// L'approche CodeFirst d'Entity Framework vous permet de gérer l'héritage entre types de trois façons différentes : + /// - héritage TPT (Table per Type) : une table par type (dont le type père) [PAS ENCORE IMPLEMENTE DANS ENTITY FRAMEWORK CORE] + /// - héritage TPH (Table per Class Hierarchy) : une seule table correspondant au type père mais avec toutes les propriétés (nullables) des types fils + /// - héritage TPC (Table per Concrete Class) : une table par type concret [PAS ENCORE IMPLEMENTE DANS ENTITY FRAMEWORK CORE] + /// + /// Cet exemple montre comment mettre en oeuvre un héritage de type TPT. + /// Chaque table correspondant à un type fils est reliée à la table correspondant au type père via une relation one to one. + /// + /// Pour la mettre en oeuvre, il suffit de préciser à Entity Framework (via des annotations de données ou la fluent API) comment mapper les types fils aux tables. + /// Dans l'exemple suivant, les types fils (Rectangle et Cercle) utilisent une annotation de données ([Table("Rectangles")] et [Table("Cercles")]) qui entrainent l'utilisation + /// d'un héritage Table Per Type. Sans ces annotations (ou les lignes de code en fluent API équivalente cf. exemples précédents), on aurait un héritage de type TPH. + /// + /// Notez bien que la classe qui dérive de DbContext ne contient qu'un DbSet de Forme. + /// + /// Après avoir exécuté l'exemple, vous pouvez vous rendre dans l'explorateur d'objets SQL Server, et constater qu'Entity Framework a créé trois tables (Formes, Rectangles et Cercles), + /// avec des relations one to one entre Formes et Rectangles et entre Formes et Cercles. + /// + public static void Main(string[] args) + { + WriteLine("TPT Inheritance is not fully implemented yet in Entity Framework Core."); + } + } +} diff --git a/p07_Persistance/ex_042_013_EF_CF_TPT_Inheritance/ex_042_013_EF_CF_TPT_Inheritance.csproj b/p07_Persistance/ex_042_013_EF_CF_TPT_Inheritance/ex_042_013_EF_CF_TPT_Inheritance.csproj new file mode 100644 index 0000000..539e343 --- /dev/null +++ b/p07_Persistance/ex_042_013_EF_CF_TPT_Inheritance/ex_042_013_EF_CF_TPT_Inheritance.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_013_EF_CF_TPT_Inheritance + Exe + ex_042_013_EF_CF_TPT_Inheritance + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Cercle.cs b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Cercle.cs new file mode 100644 index 0000000..5f14dbc --- /dev/null +++ b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Cercle.cs @@ -0,0 +1,26 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Cercle.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-07 +// +// ======================================================================== + +namespace ex_042_014_EF_CF_TPH_Inheritance +{ + /// + /// une classe fille de Forme + /// + class Cercle : Forme + { + public float Rayon { get; set; } + + public override string ToString() + { + return $"La cercle {Nom} de rayon {Rayon} est centré en ({X:0.00} ; {Y:0.00})"; + } + } +} diff --git a/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/DbContextInitializer.cs b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/DbContextInitializer.cs new file mode 100644 index 0000000..296dd16 --- /dev/null +++ b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/DbContextInitializer.cs @@ -0,0 +1,71 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-07 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_014_EF_CF_TPH_Inheritance +{ + /// + /// initialiseur de stratégies... + /// + static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(FormesDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + //données stubbées + //simulation de données en utilisant les types du Model + Forme carré = new Rectangle { Nom = "carré", Longueur = 2, Largeur = 2, X = 1, Y = 3 }; + Forme rectangle = new Rectangle { Nom = "rectangle", Longueur = 3, Largeur = 4, X = 5, Y = 6 }; + Forme cercle = new Cercle { Nom = "cercle", Rayon = 7, X = 8, Y = 9 }; + + context.FormesSet.AddRange(new Forme[] { carré, rectangle, cercle }); + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Forme.cs b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Forme.cs new file mode 100644 index 0000000..243b0e0 --- /dev/null +++ b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Forme.cs @@ -0,0 +1,37 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Forme.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-07 +// +// ======================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_014_EF_CF_TPH_Inheritance +{ + /// + /// la classe mère + /// + class Forme + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId { get; set; } + public string Nom { get; set; } + + public float X { get; set; } + + public float Y { get; set; } + + public override string ToString() + { + return $"La forme {Nom} est placée en ({X:0.00} ; {Y:0.00})"; + } + } +} diff --git a/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/FormesDBEntities.cs b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/FormesDBEntities.cs new file mode 100644 index 0000000..03e4008 --- /dev/null +++ b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/FormesDBEntities.cs @@ -0,0 +1,65 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : FormesDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-07 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; + +namespace ex_042_014_EF_CF_TPH_Inheritance +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient deux DbSet pour permettre de réaliser des opérations CRUD sur les types T, ici Forme. + /// + /// Pour permettre de réaliser un héritage de type TPH (Table Per class Hierarchy), deux méthodes s'offrent à nous : + /// METHODE 1 : + /// - déclarez un DbSet pour la classe mère + /// - déclarez un DbSet pour chaque classe fille + /// - vous pouvez utiliser des annotations de données dans les classes + /// METHODE 2 (fluent API) : + /// - réécrivez la méthode OnModelCreating, + /// - ajoutez des appels aux méthodes Entity() (une par classe fille) + /// - vous pouvez en profiter pour préciser le nom de la colonne qui sert de Discriminator, + /// et les noms associés aux classes filles dans cette colonne. + /// - le type de la classe fille se précise dans l'appel de HasValue avec T du type de la classe fille. + /// + /// Commentez et décommentez les deux méthodes pour les tester. + /// + class FormesDBEntities : DbContext + { + public virtual DbSet FormesSet { get; set; } + + //METHODE 1 : + public virtual DbSet RectanglesSet { get; set; } + public virtual DbSet CerclesSet { get; set; } + //FIN METHODE 1 + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_014_EF_CF_TPH_Inheritance.Formes.mdf;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + ////METHODE 2 : + //modelBuilder.Entity() + // .HasDiscriminator("formeType") + // .HasValue("formeBase") + // .HasValue("rectangle"); + + //modelBuilder.Entity() + // .HasDiscriminator("formeType") + // .HasValue("formeBase") + // .HasValue("cercle"); + ////FIN METHODE 2 + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Program.cs b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Program.cs new file mode 100644 index 0000000..f1e9ada --- /dev/null +++ b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Program.cs @@ -0,0 +1,53 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-07 +// +// ======================================================================== + +using static System.Console; + +namespace ex_042_014_EF_CF_TPH_Inheritance +{ + /// + /// L'approche CodeFirst d'Entity Framework vous permet de gérer l'héritage entre types de trois façons différentes : + /// - héritage TPT (Table per Type) : une table par type (dont le type père) [PAS ENCORE IMPLEMENTE DANS ENTITY FRAMEWORK CORE] + /// - héritage TPH (Table per Class Hierarchy) : une seule table correspondant au type père mais avec toutes les propriétés (nullables) des types fils + /// - héritage TPC (Table per Concrete Class) : une table par type concret [PAS ENCORE IMPLEMENTE DANS ENTITY FRAMEWORK CORE] + /// + /// Cet exemple montre comment mettre en oeuvre un héritage de type TPH. + /// Ici, il n'y aura qu'une seule table correspondant à la classe mère. Toutefois, il y aura autant de colonnes que de propriétés spécifiques dans les classes filles. + /// Les valeurs seront nullables : si l'objet est de type A, toutes valeurs des colonnes correspondant au type B seront nulles. + /// + /// Pour la mettre en oeuvre, il suffit de ne rien faire ! Il ne faut utiliser aucune annotations de données sur les classes filles, et ne pas utiliser la fluent API pour les classes filles. + /// Dans l'exemple suivant, les types fils (Rectangle et Cercle) n'utilisent aucune annotation de données ([Table("Rectangles")] et [Table("Cercles")]) et aucune ligne de code en fluent API dans la classe DbContext. + /// + /// Notez bien que la classe qui dérive de DbContext ne contient qu'un DbSet de Forme. + /// + /// Après avoir exécuté l'exemple, vous pouvez vous rendre dans l'explorateur d'objets SQL Server, et constater qu'Entity Framework a créé une seule table (Formes). + /// Notez la présence de la colonne Discriminator qui indique quel est le type concret de l'objet correspondant à la ligne. + /// Notez également la présence des colonnes Longueur et Largeur (pourtant spécificiques à Rectangle) et Rayon (pourtant spécifique à Cercle) qui ont des valeurs nulles si le type fils n'a pas ces propriétés. + /// + public class Program + { + public static void Main(string[] args) + { + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (FormesDBEntities db = new FormesDBEntities()) + { + //choix de la stratégie et remplissage avec des données stubbées + DbContextInitializer.Seed(db); + + WriteLine("formes : "); + foreach (var f in db.FormesSet) + { + WriteLine($"\t{f}"); + } + } + } + } +} diff --git a/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Rectangle.cs b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Rectangle.cs new file mode 100644 index 0000000..c86bede --- /dev/null +++ b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/Rectangle.cs @@ -0,0 +1,30 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Rectangle.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-07 +// +// ======================================================================== + +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_014_EF_CF_TPH_Inheritance +{ + /// + /// une classe fille de Forme + /// + class Rectangle : Forme + { + public float Longueur { get; set; } + + public float Largeur { get; set; } + + public override string ToString() + { + return $"La rectangle {Nom} de longueur {Longueur} et de largeur {Largeur} est placé en ({X:0.00} ; {Y:0.00})"; + } + } +} diff --git a/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/ex_042_014_EF_CF_TPH_Inheritance.csproj b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/ex_042_014_EF_CF_TPH_Inheritance.csproj new file mode 100644 index 0000000..25433b2 --- /dev/null +++ b/p07_Persistance/ex_042_014_EF_CF_TPH_Inheritance/ex_042_014_EF_CF_TPH_Inheritance.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_014_EF_CF_TPH_Inheritance + Exe + ex_042_014_EF_CF_TPH_Inheritance + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_015_EF_CF_TPC_Inheritance/Program.cs b/p07_Persistance/ex_042_015_EF_CF_TPC_Inheritance/Program.cs new file mode 100644 index 0000000..08c26c9 --- /dev/null +++ b/p07_Persistance/ex_042_015_EF_CF_TPC_Inheritance/Program.cs @@ -0,0 +1,42 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-07 +// +// ======================================================================== + +using static System.Console; + +namespace ex_042_015_EF_CF_TPC_Inheritance +{ + /// + /// L'approche CodeFirst d'Entity Framework vous permet de gérer l'héritage entre types de trois façons différentes : + /// - héritage TPT (Table per Type) : une table par type (dont le type père) [PAS ENCORE IMPLEMENTE DANS ENTITY FRAMEWORK CORE] + /// - héritage TPH (Table per Class Hierarchy) : une seule table correspondant au type père mais avec toutes les propriétés (nullables) des types fils + /// - héritage TPC (Table per Concrete Class) : une table par type concret [PAS ENCORE IMPLEMENTE DANS ENTITY FRAMEWORK CORE] + /// + /// Cet exemple montre comment mettre en oeuvre un héritage de type TPC. + /// Ici, il n'y aura une table par type concret, et aucune pour les types abstraits. L'inconvénient est la duplication des colonnes dans les types concrets. + /// C'est solution ne marche que lorsque le type père est abstrait. + /// + /// Pour la mettre en oeuvre, il faut : + /// - que la classe mère soit abstraite (mais elle peut quand même contenir des annotations de données), sinon, une table sera créée pour elle, même si elle est vide + /// - dans la classe qui dérive de DbContext, utiiser des "Map" pour expliquer qu'il faut hériter les propriétés de la classe mère et mapper chaque entité à une table + /// (- note importante : avec l'héritage TPC, vous ne pouvez pas utiliser d'identifiant entier généré automatiquement. Il faut utiliser un identifiant de type Guid, sinon, il va générer plusieurs entités avec le même id.) + /// + /// Notez bien que la classe qui dérive de DbContext ne contient qu'un DbSet de Forme. + /// + /// Après avoir exécuté l'exemple, vous pouvez vous rendre dans l'explorateur d'objets SQL Server, et constater qu'Entity Framework a créé une table par type concret, et aucune table pour la classe mère. + /// + class Program + { + static void Main(string[] args) + { + WriteLine("TPC Inheritance is not fully implemented yet in Entity Framework Core."); + } + } +} diff --git a/p07_Persistance/ex_042_015_EF_CF_TPC_Inheritance/ex_042_015_EF_CF_TPC_Inheritance.csproj b/p07_Persistance/ex_042_015_EF_CF_TPC_Inheritance/ex_042_015_EF_CF_TPC_Inheritance.csproj new file mode 100644 index 0000000..3ebd9c3 --- /dev/null +++ b/p07_Persistance/ex_042_015_EF_CF_TPC_Inheritance/ex_042_015_EF_CF_TPC_Inheritance.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_042_015_EF_CF_TPC_Inheritance + Exe + ex_042_015_EF_CF_TPC_Inheritance + 6.0.6 + false + false + false + + diff --git a/p07_Persistance/ex_042_016_EF_current_original_database_val/DbContextInitializer.cs b/p07_Persistance/ex_042_016_EF_current_original_database_val/DbContextInitializer.cs new file mode 100644 index 0000000..c54cc35 --- /dev/null +++ b/p07_Persistance/ex_042_016_EF_current_original_database_val/DbContextInitializer.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_016_EF_current_original_database_val +{ + /// + /// initialiseur de stratégies... + /// + static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(NounoursDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Nounours chewie = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 }; + Nounours yoda = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 }; + Nounours ewok = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 }; + + context.NounoursSet.AddRange(new Nounours[] { chewie, yoda, ewok }); + + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_016_EF_current_original_database_val/Nounours.cs b/p07_Persistance/ex_042_016_EF_current_original_database_val/Nounours.cs new file mode 100644 index 0000000..6dd0925 --- /dev/null +++ b/p07_Persistance/ex_042_016_EF_current_original_database_val/Nounours.cs @@ -0,0 +1,103 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_016_EF_current_original_database_val +{ + /// + /// Nounours est une classe POCO, i.e. Plain Old CLR Object. + /// + [Table("TableNounours")] + public class Nounours + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + [Required] + [MaxLength(256)] + public string Nom + { + get; + set; + } + + [Column("Naissance")] + public DateTime DateDeNaissance + { + get; + set; + } + + public int NbPoils + { + get; + set; + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{UniqueId}: {Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_042_016_EF_current_original_database_val/NounoursDBEntities.cs b/p07_Persistance/ex_042_016_EF_current_original_database_val/NounoursDBEntities.cs new file mode 100644 index 0000000..01ede25 --- /dev/null +++ b/p07_Persistance/ex_042_016_EF_current_original_database_val/NounoursDBEntities.cs @@ -0,0 +1,29 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; + +namespace ex_042_016_EF_current_original_database_val +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient un DbSet pour permettre de réaliser des opérations CRUD sur le type T, ici Nounours. + /// + class NounoursDBEntities : DbContext + { + public virtual DbSet NounoursSet { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_016_EF_current_original_database_val.Nounours.mdf;Trusted_Connection=True;"); + } + } +} diff --git a/p07_Persistance/ex_042_016_EF_current_original_database_val/Program.cs b/p07_Persistance/ex_042_016_EF_current_original_database_val/Program.cs new file mode 100644 index 0000000..0a9590e --- /dev/null +++ b/p07_Persistance/ex_042_016_EF_current_original_database_val/Program.cs @@ -0,0 +1,102 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using static System.Console; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; + +namespace ex_042_016_EF_current_original_database_val +{ + /// + /// Cet exemple montre à quoi correspondent les valeurs CurrrentValues, OriginalValues et DabaseValues et comment les obtenir depuis Entity Framework Core. + /// Ici, on montre donc une entrée dans la base dont la propriété Nom est modifiée. + /// + class Program + { + public static void PrintValues(EntityEntry entry, NounoursDBEntities context, Values values) + { + foreach (var property in entry.Metadata.GetProperties()) + { + switch(values) + { + case Values.Current: + WriteLine($"La propriété {property.Name} a la valeur {entry.Property(property.Name).CurrentValue}"); + break; + case Values.Original: + WriteLine($"La propriété {property.Name} a la valeur {entry.Property(property.Name).OriginalValue}"); + break; + case Values.Database: + // Using a NoTracking query means we get the entity but it is not tracked by the context + // and will not be merged with existing entities in the context. + var databaseEntity = context.NounoursSet.AsNoTracking().Single(n => n.UniqueId == (entry.Entity as Nounours).UniqueId); + //récupère l'entry correspondante dans la base + var databaseEntry = context.Entry(databaseEntity); + WriteLine($"La propriété {property.Name} a la valeur {databaseEntry.Property(property.Name).CurrentValue}"); + break; + } + } + } + + public enum Values + { + Current, + Original, + Database + } + + static void Main(string[] args) + { + using (var context = new NounoursDBEntities()) + { + //choix de la stratégie et remplissage avec des données stubbées + DbContextInitializer.Seed(context); + } + + using (var context = new NounoursDBEntities()) + { + var ids = context.NounoursSet.Select(n => n.UniqueId).ToList(); + + //on récupère le premier Nounours + WriteLine("On récupère le premier Nounours de la base : son nom est \"Chewbacca\"\n"); + var nounours = context.NounoursSet.Single(n => n.UniqueId == ids[0]); + + // On réalise une modification de la propriété Nom de l'entité récupérée + WriteLine("On réalise une modification de la propriété Nom de l'entité récupérée : son nom est changé de \"Chewbacca\" à \"Chewie\"."); + WriteLine("(en local, les changements ne sont pas encore enregistrés)\n"); + + nounours.Nom = "Chewie"; + + // Pendant ce temps, l'entité correspondante en base de données est modifiée (la colonne Nom) + WriteLine("Pendant ce temps, l'entité correspondante en base de données est modifiée (la colonne Nom) : le nom est changé de \"Chewbacca\" à \"Boules de poils\"."); + WriteLine("(les changements sont ici effectués sur la base)\n"); + context.Database.ExecuteSqlCommand($"update dbo.TableNounours set Nom = 'Boule de poils' where UniqueId = {ids[0]}"); + + // Affichage des données dites "courantes" CurrentValues + WriteLine("Current values:"); + PrintValues(context.Entry(nounours), context, Values.Current); + + // Affichage des données dites "originales" OriginalValues + WriteLine("\nOriginal values:"); + PrintValues(context.Entry(nounours), context, Values.Original);//.OriginalValues); + + // Affichage des données dites "base de données" DatabaseValues + WriteLine("\nDatabase values:"); + PrintValues(context.Entry(nounours), context, Values.Database);//.GetDatabaseValues()); + + WriteLine(); + WriteLine("Remarquez que CurrentValues correspond aux données de l'entité en cours de modification,"); + WriteLine("Remarquez que OriginalValues correspond aux données de l'entité récupérée juste avant modification,"); + WriteLine("Remarquez que DatabaseValues correspond aux données de l'entité telles que sont en base de données."); + } + } + } +} diff --git a/p07_Persistance/ex_042_016_EF_current_original_database_val/ex_042_016_EF_current_original_database_val.csproj b/p07_Persistance/ex_042_016_EF_current_original_database_val/ex_042_016_EF_current_original_database_val.csproj new file mode 100644 index 0000000..e470b5c --- /dev/null +++ b/p07_Persistance/ex_042_016_EF_current_original_database_val/ex_042_016_EF_current_original_database_val.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_016_EF_current_original_database_val + Exe + ex_042_016_EF_current_original_database_val + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_017_EF_concurrency_problematic/DbContextInitializer.cs b/p07_Persistance/ex_042_017_EF_concurrency_problematic/DbContextInitializer.cs new file mode 100644 index 0000000..bf37165 --- /dev/null +++ b/p07_Persistance/ex_042_017_EF_concurrency_problematic/DbContextInitializer.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_017_EF_concurrency_problematic +{ + /// + /// initialiseur de stratégies... + /// + static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(NounoursDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Nounours chewie = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 }; + Nounours yoda = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 }; + Nounours ewok = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 }; + + context.NounoursSet.AddRange(new Nounours[] { chewie, yoda, ewok }); + + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_017_EF_concurrency_problematic/Nounours.cs b/p07_Persistance/ex_042_017_EF_concurrency_problematic/Nounours.cs new file mode 100644 index 0000000..e48c3de --- /dev/null +++ b/p07_Persistance/ex_042_017_EF_concurrency_problematic/Nounours.cs @@ -0,0 +1,103 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_017_EF_concurrency_problematic +{ + /// + /// Nounours est une classe POCO, i.e. Plain Old CLR Object. + /// + [Table("TableNounours")] + public class Nounours + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + [Required] + [MaxLength(256)] + public string Nom + { + get; + set; + } + + [Column("Naissance")] + public DateTime DateDeNaissance + { + get; + set; + } + + public int NbPoils + { + get; + set; + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{UniqueId}: {Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_042_017_EF_concurrency_problematic/NounoursDBEntities.cs b/p07_Persistance/ex_042_017_EF_concurrency_problematic/NounoursDBEntities.cs new file mode 100644 index 0000000..ba626fe --- /dev/null +++ b/p07_Persistance/ex_042_017_EF_concurrency_problematic/NounoursDBEntities.cs @@ -0,0 +1,29 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; + +namespace ex_042_017_EF_concurrency_problematic +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient un DbSet pour permettre de réaliser des opérations CRUD sur le type T, ici Nounours. + /// + class NounoursDBEntities : DbContext + { + public virtual DbSet NounoursSet { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_017_EF_concurrency_problematic.Nounours.mdf;Trusted_Connection=True;"); + } + } +} diff --git a/p07_Persistance/ex_042_017_EF_concurrency_problematic/Program.cs b/p07_Persistance/ex_042_017_EF_concurrency_problematic/Program.cs new file mode 100644 index 0000000..9115f9a --- /dev/null +++ b/p07_Persistance/ex_042_017_EF_concurrency_problematic/Program.cs @@ -0,0 +1,129 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-12 +// +// ======================================================================== + +using static System.Console; +using System.Linq; +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; + +namespace ex_042_017_EF_concurrency_problematic +{ + /// + /// Cet exemple montre à quoi correspondent les valeurs CurrrentValues, OriginalValues et DabaseValues et comment les obtenir depuis Entity Framework Core. + /// Ici, on montre donc une entrée dans la base dont la propriété Nom est modifiée. + /// + class Program + { + /// + /// récupère un Nounours à partir de son id + /// + /// l'id du Nounours à récupérer + /// le Nounours récupéré (null, si l'id n'est pas connu dans la base) + static Nounours GetNounours(Guid id) + { + Nounours nounours = null; + + using (NounoursDBEntities db = new NounoursDBEntities()) + { + nounours = db.NounoursSet.Single(n => n.UniqueId == id); + } + + return nounours; + } + + /// + /// mise à jour du Nounours dans la base + /// + /// nounours à mettre à jour + static void UpdateNounours(Nounours nounours) + { + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.NounoursSet.Attach(nounours); + db.Entry(nounours).State = EntityState.Modified; + + db.SaveChanges(); + } + } + + static void Main(string[] args) + { + List ids = new List(); + + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (NounoursDBEntities db = new NounoursDBEntities()) + { + //choix de la stratégie et remplissage avec des données stubbées + DbContextInitializer.Seed(db); + + //récupère la liste des ids + ids = db.NounoursSet.Select(n => n.UniqueId).ToList(); + } + + PrintTable("Au démarrage, la table contient :"); + + WriteLine(); + + //DEBUT DE LA SIMULATION DE MISES A JOUR CONCURRENTES + + //1. Le premier utilisateur récupère les données du premier nounours + Nounours nounours1 = GetNounours(ids[0]); + WriteLine("L'utilisateur 1 récupère le premier nounours"); + + //2. Le deuxième utilisateur réupère les données du premier nounours + Nounours nounours2 = GetNounours(ids[0]); + WriteLine("L'utilisateur 2 récupère le premier nounours"); + + //jusque-là, la table contient : + // "Chewbacca", 27/05/1977, 1234567 poils + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //3. Le premier utilisateur tente de mettre à jour le nombre de poils + nounours1.NbPoils = 2; + UpdateNounours(nounours1); + PrintTable("Après la tentative de modification du nombre de poils de Chewbacca à 2 par l'utilisateur 1 :"); + + //maintenant, la table contient : + // "Chewbacca", 27/05/1977, 2 poils <========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //4. Le deuxième utilisateur tente de mettre à jour la propriété Date De Naissance + nounours2.DateDeNaissance = DateTime.Today; + UpdateNounours(nounours2); + PrintTable("Après la tentative de modification de la date de naissance de Chewbacca à aujourd'hui par l'utilisateur 2 :"); + + //maintenant, la table contient : + // "Chewbacca", 07/11/2016, 1234567 poils <=========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //Remarquez que le nombre de poils a été écrasé par la propriété précédente, car le deuxième utilisateur a récupéré le nounours avant la première modification. + } + + static void PrintTable(string intro) + { + WriteLine(); + WriteLine(intro); + using (NounoursDBEntities db = new NounoursDBEntities()) + { + //affiche les nounours après les modifications + WriteLine("Après modifications"); + foreach (var n in db.NounoursSet) + { + WriteLine($"\t{n}"); + } + } + } + } +} diff --git a/p07_Persistance/ex_042_017_EF_concurrency_problematic/ex_042_017_EF_concurrency_problematic.csproj b/p07_Persistance/ex_042_017_EF_concurrency_problematic/ex_042_017_EF_concurrency_problematic.csproj new file mode 100644 index 0000000..7920462 --- /dev/null +++ b/p07_Persistance/ex_042_017_EF_concurrency_problematic/ex_042_017_EF_concurrency_problematic.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_017_EF_concurrency_problematic + Exe + ex_042_017_EF_concurrency_problematic + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/DbContextInitializer.cs b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/DbContextInitializer.cs new file mode 100644 index 0000000..fcb513f --- /dev/null +++ b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/DbContextInitializer.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_018_EF_concurrency_databaseWins +{ + /// + /// initialiseur de stratégies... + /// + static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(NounoursDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Nounours chewie = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 }; + Nounours yoda = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 }; + Nounours ewok = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 }; + + context.NounoursSet.AddRange(new Nounours[] { chewie, yoda, ewok }); + + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/Nounours.cs b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/Nounours.cs new file mode 100644 index 0000000..c78a014 --- /dev/null +++ b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/Nounours.cs @@ -0,0 +1,111 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_018_EF_concurrency_databaseWins +{ + /// + /// Nounours est une classe POCO, i.e. Plain Old CLR Object. + /// + [Table("TableNounours")] + public class Nounours + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + [Required] + [MaxLength(256)] + public string Nom + { + get; + set; + } + + [Column("Naissance")] + //METHODE 2a : + //On ajoute un décorateur sur les propriétés DateDeNaissance et NbPoils (par exemple) + [ConcurrencyCheck] + //FIN METHODE 2a + public DateTime DateDeNaissance + { + get; + set; + } + + //METHODE 2a : + //On ajoute un décorateur sur les propriétés DateDeNaissance et NbPoils (par exemple) + [ConcurrencyCheck] + //FIN METHODE 2a + public int NbPoils + { + get; + set; + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{UniqueId}: {Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/NounoursDBEntities.cs b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/NounoursDBEntities.cs new file mode 100644 index 0000000..cdb221a --- /dev/null +++ b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/NounoursDBEntities.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-11 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_018_EF_concurrency_databaseWins +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient un DbSet pour permettre de réaliser des opérations CRUD sur le type T, ici Nounours. + /// + class NounoursDBEntities : DbContext + { + public virtual DbSet NounoursSet { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_018_EF_concurrency_databaseWins.Nounours.mdf;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + ////METHODE 2b + ////On précise que NbPoils et DateDeNaissance sont utilisés pour les tests de vérification de modifications ou suppressions concurrentes. + //modelBuilder.Entity().Property(n => n.NbPoils).IsConcurrencyToken(); + //modelBuilder.Entity().Property(n => n.DateDeNaissance).IsConcurrencyToken(); + ////FIN METHODE 2b + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/Program.cs b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/Program.cs new file mode 100644 index 0000000..6ca046c --- /dev/null +++ b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/Program.cs @@ -0,0 +1,157 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-12 +// +// ======================================================================== + +using static System.Console; +using System.Linq; +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; + +namespace ex_042_018_EF_concurrency_databaseWins +{ + /// + /// Cet exemple simule des mises à jours concurrentes de données dans la table. + /// Contrairement à l'exemple précédent, il montre comment il est possible de gérer facilement ces insertions concurrentes avec EntityFramework. + /// Il laisse la priorité à la base de données, c'est-à-dire que si le client essaye de modifier les données alors qu'elles ont été modifiées entre sa récupération et sa mise à jour, + /// son action est rejetée. + /// Cette méthode est souvent appelée "Database Wins" et change l'état de l'entité en cours de modification pour donner la priorité à la base de données. + /// + /// Deux méthodes sont proposées pour cela : + /// - (METHODE 1) : la première consiste à dédier une colonne pour les vérifications (update et delete) qu'on appelle généralement RowVersion et qu'on décore avec l'attribut Timestamp (cf. classe Nounours) + /// - la seconde permet de ne pas rajouter de colonne spécifique mais de préciser quelles seront les colonnes à utiliser pour les tests de vérification + /// - (METHODE 2a) : soit en annotation de données ([ConcurrencyCheck()]) (cf. classe Nounours) + /// - (METHODE 2b) : soit en fluent API (modelBuilder.Entity().Property(n => n.NbPoils).IsConcurrencyToken();) (cf. classe NounoursDBEntities) + /// + /// Attention de bien noter que la méthode UpdateNounours a été modifiée pour catcher l'exception DbUpdateConcurrencyException et appeler la méthode Reload() en cas d'exception. + /// + /// Commentez et décommentez les méthodes pour tester les différentes possibilités + /// + class Program + { + /// + /// récupère un Nounours à partir de son id + /// + /// l'id du Nounours à récupérer + /// le Nounours récupéré (null, si l'id n'est pas connu dans la base) + static Nounours GetNounours(Guid id) + { + Nounours nounours = null; + + using (NounoursDBEntities db = new NounoursDBEntities()) + { + nounours = db.NounoursSet.Single(n => n.UniqueId == id); + } + + return nounours; + } + + /// + /// mise à jour du Nounours dans la base + /// + /// nounours à mettre à jour + static void UpdateNounours(Nounours nounours) + { + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.NounoursSet.Attach(nounours); + db.Entry(nounours).State = EntityState.Modified; + + try + { + db.SaveChanges(); + } + catch (DbUpdateConcurrencyException ex) + { + //observez en mode debug de quelle manière la variable nounours est affectée par l'instruction suivante + ex.Entries.Single().State = EntityState.Unchanged; + db.SaveChanges(); + } + } + } + + static void Main(string[] args) + { + List ids = new List(); + + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (NounoursDBEntities db = new NounoursDBEntities()) + { + DbContextInitializer.Seed(db); + + //récupère la liste des ids + ids = db.NounoursSet.Select(n => n.UniqueId).ToList(); + } + + PrintTable("Au démarrage, la table contient :"); + + WriteLine(); + + //DEBUT DE LA SIMULATION DE MISES A JOUR CONCURRENTES + + //1. Le premier utilisateur récupère les données du premier nounours + Nounours nounours1 = GetNounours(ids[0]); + WriteLine("L'utilisateur 1 récupère le premier nounours"); + + //2. Le deuxième utilisateur réupère les données du premier nounours + Nounours nounours2 = GetNounours(ids[0]); + WriteLine("L'utilisateur 2 récupère le premier nounours"); + + //jusque-là, la table contient : + // "Chewbacca", 27/05/1977, 1234567 poils + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //3. Le premier utilisateur tente de mettre à jour le nombre de poils, mais ne met pas tout de suite la table à jour + nounours1.NbPoils = 2; + + WriteLine("Soudain, la table est modifiée par des facteurs extérieurs... (un recommandé peut-être...)"); + //4. La table est mise à jour par un autre biais + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.Database.ExecuteSqlCommand($"UPDATE dbo.TableNounours SET NbPoils = 5 WHERE UniqueId = {ids[0]}"); + db.SaveChanges(); + } + PrintTable("Maintenant, la table contient :"); + //maintenant, la table contient : + // "Chewbacca", 27/05/1977, 5 poils <========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //5. L'utilisateur 1 tente de mettre à jour le nombre de poils + UpdateNounours(nounours1); + PrintTable("Après la tentative de modification du nombre de poils de Chewbacca à 2 par l'utilisateur 1 :"); + //une exception est lancée. + //En database wins, nounours1 est modifié et son nombre de poils passe à 5. + + //6. Le deuxième utilisateur tente de mettre à jour la propriété Date De Naissance + nounours2.DateDeNaissance = DateTime.Today; + UpdateNounours(nounours2); + PrintTable("Après la tentative de modification de la date de naissance de Chewbacca à aujourd'hui par l'utilisateur 2 :"); + //une exception est lancée. + //En database wins, nounours2 est modifié et sa date de naissance repasse au 27/05/1977. + } + + static void PrintTable(string intro) + { + WriteLine(); + WriteLine(intro); + using (NounoursDBEntities db = new NounoursDBEntities()) + { + //affiche les nounours après les modifications + WriteLine("Après modifications"); + foreach (var n in db.NounoursSet) + { + WriteLine($"\t{n}"); + } + } + } + } +} diff --git a/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/ex_042_018_EF_concurrency_databaseWins.csproj b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/ex_042_018_EF_concurrency_databaseWins.csproj new file mode 100644 index 0000000..0e8ea6a --- /dev/null +++ b/p07_Persistance/ex_042_018_EF_concurrency_databaseWins/ex_042_018_EF_concurrency_databaseWins.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_018_EF_concurrency_databaseWins + Exe + ex_042_018_EF_concurrency_databaseWins + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_019_EF_concurrency_clientWins/DbContextInitializer.cs b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/DbContextInitializer.cs new file mode 100644 index 0000000..dc34f70 --- /dev/null +++ b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/DbContextInitializer.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-12 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_019_EF_concurrency_clientWins +{ + /// + /// initialiseur de stratégies... + /// + static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(NounoursDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Nounours chewie = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 }; + Nounours yoda = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 }; + Nounours ewok = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 }; + + context.NounoursSet.AddRange(new Nounours[] { chewie, yoda, ewok }); + + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_019_EF_concurrency_clientWins/Nounours.cs b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/Nounours.cs new file mode 100644 index 0000000..540a804 --- /dev/null +++ b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/Nounours.cs @@ -0,0 +1,111 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-12 +// +// ======================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_019_EF_concurrency_clientWins +{ + /// + /// Nounours est une classe POCO, i.e. Plain Old CLR Object. + /// + [Table("TableNounours")] + public class Nounours + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + [Required] + [MaxLength(256)] + public string Nom + { + get; + set; + } + + [Column("Naissance")] + //METHODE 2a : + //On ajoute un décorateur sur les propriétés DateDeNaissance et NbPoils (par exemple) + [ConcurrencyCheck] + //FIN METHODE 2a + public DateTime DateDeNaissance + { + get; + set; + } + + //METHODE 2a : + //On ajoute un décorateur sur les propriétés DateDeNaissance et NbPoils (par exemple) + [ConcurrencyCheck] + //FIN METHODE 2a + public int NbPoils + { + get; + set; + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{UniqueId}: {Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_042_019_EF_concurrency_clientWins/NounoursDBEntities.cs b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/NounoursDBEntities.cs new file mode 100644 index 0000000..353ee5a --- /dev/null +++ b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/NounoursDBEntities.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-12 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_019_EF_concurrency_clientWins +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient un DbSet pour permettre de réaliser des opérations CRUD sur le type T, ici Nounours. + /// + class NounoursDBEntities : DbContext + { + public virtual DbSet NounoursSet { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_019_EF_concurrency_clientWins.Nounours.mdf;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + ////METHODE 2b + ////On précise que NbPoils et DateDeNaissance sont utilisés pour les tests de vérification de modifications ou suppressions concurrentes. + //modelBuilder.Entity().Property(n => n.NbPoils).IsConcurrencyToken(); + //modelBuilder.Entity().Property(n => n.DateDeNaissance).IsConcurrencyToken(); + ////FIN METHODE 2b + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/p07_Persistance/ex_042_019_EF_concurrency_clientWins/Program.cs b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/Program.cs new file mode 100644 index 0000000..d0ec7af --- /dev/null +++ b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/Program.cs @@ -0,0 +1,184 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-12 +// +// ======================================================================== + +using static System.Console; +using System.Linq; +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; + +namespace ex_042_019_EF_concurrency_clientWins +{ + /// + /// Cet exemple simule des mises à jours concurrentes de données dans la table. + /// Contrairement à l'exemple 042_017, il montre comment il est possible de gérer facilement ces insertions concurrentes avec EntityFramework. + /// Contrairement à l'exemple 042_018, il ne laisse pas la priorité à la base de données, mais au client, + /// c'est-à-dire que si le client essaye de modifier les données alors qu'elles ont été modifiées entre sa récupération et sa mise à jour, + /// son action écrase les nouvelles données en base. + /// Cette méthode est souvent appelée "Client Wins" et utilise les données originales et en base (cf. exemple 042_016). + /// + /// Deux méthodes sont proposées pour cela : + /// - (METHODE 1) : la première consiste à dédier une colonne pour les vérifications (update et delete) qu'on appelle généralement RowVersion et qu'on décore avec l'attribut Timestamp (cf. classe Nounours) + /// - la seconde permet de ne pas rajouter de colonne spécifique mais de préciser quelles seront les colonnes à utiliser pour les tests de vérification + /// - (METHODE 2a) : soit en annotation de données ([ConcurrencyCheck()]) (cf. classe Nounours) + /// - (METHODE 2b) : soit en fluent API (modelBuilder.Entity().Property(n => n.NbPoils).IsConcurrencyToken();) (cf. classe NounoursDBEntities) + /// + /// Attention de bien noter que la méthode UpdateNounours a été modifiée pour catcher l'exception DbUpdateConcurrencyException et utiliser OriginalValues et DatabaseValues en cas d'exception. + /// + /// Commentez et décommentez les méthodes pour tester les différentes possibilités + /// + class Program + { + /// + /// récupère un Nounours à partir de son id + /// + /// l'id du Nounours à récupérer + /// le Nounours récupéré (null, si l'id n'est pas connu dans la base) + static Nounours GetNounours(Guid id) + { + Nounours nounours = null; + + using (NounoursDBEntities db = new NounoursDBEntities()) + { + nounours = db.NounoursSet.Single(n => n.UniqueId == id); + } + + return nounours; + } + + /// + /// mise à jour du Nounours dans la base + /// + /// nounours à mettre à jour + static void UpdateNounours(Nounours nounours) + { + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.NounoursSet.Attach(nounours); + db.Entry(nounours).State = EntityState.Modified; + + try + { + db.SaveChanges(); + } + catch (DbUpdateConcurrencyException ex) + { + //observez en mode debug de quelle manière la variable nounours est affectée + //récupération de l'entry + var entry = ex.Entries.Single(); + // Using a NoTracking query means we get the entity but it is not tracked by the context + // and will not be merged with existing entities in the context. + var databaseEntity = db.NounoursSet.AsNoTracking().Single(n => n.UniqueId== (entry.Entity as Nounours).UniqueId); + var databaseEntry = db.Entry(databaseEntity); + + //on change les données OriginalValues en les écrasant avec celles en base. + //Ainsi, EF ne voit pas de différences entre les données récupérées en base avant et après les modifications, et croit qu'on peut faire une modification avec CurrentValues + foreach (var property in entry.Metadata.GetProperties()) + { + entry.Property(property.Name).OriginalValue = databaseEntry.Property(property.Name).CurrentValue; + } + + //on applique les données courantes en base + db.SaveChanges(); + + } + } + } + + static void Main(string[] args) + { + List ids = new List(); + + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (NounoursDBEntities db = new NounoursDBEntities()) + { + DbContextInitializer.Seed(db); + + //récupère la liste des ids + ids = db.NounoursSet.Select(n => n.UniqueId).ToList(); + } + + PrintTable("Au démarrage, la table contient :"); + + WriteLine(); + + //DEBUT DE LA SIMULATION DE MISES A JOUR CONCURRENTES + + //1. Le premier utilisateur récupère les données du premier nounours + Nounours nounours1 = GetNounours(ids[0]); + WriteLine("L'utilisateur 1 récupère le premier nounours"); + + //2. Le deuxième utilisateur réupère les données du premier nounours + Nounours nounours2 = GetNounours(ids[0]); + WriteLine("L'utilisateur 2 récupère le premier nounours"); + + //jusque-là, la table contient : + // "Chewbacca", 27/05/1977, 1234567 poils + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //3. Le premier utilisateur tente de mettre à jour le nombre de poils, mais ne met pas tout de suite la table à jour + nounours1.NbPoils = 2; + + WriteLine("Soudain, la table est modifiée par des facteurs extérieurs... (un recommandé peut-être...)"); + //4. La table est mise à jour par un autre biais + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.Database.ExecuteSqlCommand($"UPDATE dbo.TableNounours SET NbPoils = 5 WHERE UniqueId = {ids[0]}"); + db.SaveChanges(); + } + PrintTable("Maintenant, la table contient :"); + //maintenant, la table contient : + // "Chewbacca", 27/05/1977, 5 poils <========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //5. L'utilisateur 1 tente de mettre à jour le nombre de poils + UpdateNounours(nounours1); + PrintTable("Après la tentative de modification du nombre de poils de Chewbacca à 2 par l'utilisateur 1 :"); + //une exception est lancée. + //En client wins, nounours1 écrase les données dans la table. + + //maintenant, la table contient : + // "Chewbacca", 27/05/1977, 2 poils <========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //6. Le deuxième utilisateur tente de mettre à jour la propriété Date De Naissance + nounours2.DateDeNaissance = DateTime.Today; + UpdateNounours(nounours2); + PrintTable("Après la tentative de modification de la date de naissance de Chewbacca à aujourd'hui par l'utilisateur 2 :"); + //une exception est lancée. + // En client wins, nounours2 écrase les données en table + + //maintenant, la table contient : + // "Chewbacca", 10/11/2016, 1234567 poils <========================= + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + //Notez que le nombre de poils a à nouveau changé, car nounours2 avait récupéré les données avant la première insertion + } + + static void PrintTable(string intro) + { + WriteLine(); + WriteLine(intro); + using (NounoursDBEntities db = new NounoursDBEntities()) + { + //affiche les nounours après les modifications + WriteLine("Après modifications"); + foreach (var n in db.NounoursSet) + { + WriteLine($"\t{n}"); + } + } + } + } +} diff --git a/p07_Persistance/ex_042_019_EF_concurrency_clientWins/ex_042_019_EF_concurrency_clientWins.csproj b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/ex_042_019_EF_concurrency_clientWins.csproj new file mode 100644 index 0000000..d963ac4 --- /dev/null +++ b/p07_Persistance/ex_042_019_EF_concurrency_clientWins/ex_042_019_EF_concurrency_clientWins.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_019_EF_concurrency_clientWins + Exe + ex_042_019_EF_concurrency_clientWins + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/DbContextInitializer.cs b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/DbContextInitializer.cs new file mode 100644 index 0000000..0ac58b3 --- /dev/null +++ b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/DbContextInitializer.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-13 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_020_EF_concurrency_customDbProp +{ + /// + /// initialiseur de stratégies... + /// + static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(NounoursDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Nounours chewie = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 }; + Nounours yoda = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 }; + Nounours ewok = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 }; + + context.NounoursSet.AddRange(new Nounours[] { chewie, yoda, ewok }); + + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/Nounours.cs b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/Nounours.cs new file mode 100644 index 0000000..3d121b9 --- /dev/null +++ b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/Nounours.cs @@ -0,0 +1,111 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-13 +// +// ======================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_020_EF_concurrency_customDbProp +{ + /// + /// Nounours est une classe POCO, i.e. Plain Old CLR Object. + /// + [Table("TableNounours")] + public class Nounours + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + [Required] + [MaxLength(256)] + public string Nom + { + get; + set; + } + + [Column("Naissance")] + //METHODE 2a : + //On ajoute un décorateur sur les propriétés DateDeNaissance et NbPoils (par exemple) + [ConcurrencyCheck] + //FIN METHODE 2a + public DateTime DateDeNaissance + { + get; + set; + } + + //METHODE 2a : + //On ajoute un décorateur sur les propriétés DateDeNaissance et NbPoils (par exemple) + [ConcurrencyCheck] + //FIN METHODE 2a + public int NbPoils + { + get; + set; + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{UniqueId}: {Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/NounoursDBEntities.cs b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/NounoursDBEntities.cs new file mode 100644 index 0000000..4265b12 --- /dev/null +++ b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/NounoursDBEntities.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-13 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_020_EF_concurrency_customDbProp +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient un DbSet pour permettre de réaliser des opérations CRUD sur le type T, ici Nounours. + /// + class NounoursDBEntities : DbContext + { + public virtual DbSet NounoursSet { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_020_EF_concurrency_customDbProp.Nounours.mdf;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + ////METHODE 2b + ////On précise que NbPoils et DateDeNaissance sont utilisés pour les tests de vérification de modifications ou suppressions concurrentes. + //modelBuilder.Entity().Property(n => n.NbPoils).IsConcurrencyToken(); + //modelBuilder.Entity().Property(n => n.DateDeNaissance).IsConcurrencyToken(); + ////FIN METHODE 2b + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/Program.cs b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/Program.cs new file mode 100644 index 0000000..04de60f --- /dev/null +++ b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/Program.cs @@ -0,0 +1,233 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-13 +// +// ======================================================================== + +using static System.Console; +using System.Linq; +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; + +namespace ex_042_020_EF_concurrency_customDbProp +{ + /// + /// Cet exemple simule des mises à jours concurrentes de données dans la table. + /// Contrairement à l'exemple 042_017, il montre comment il est possible de gérer facilement ces insertions concurrentes avec EntityFramework. + /// Contrairement aux exemples 042_018 et 042_019, il ne laisse pas la priorité à la base de données ou au client, mais demande à l'utilisateur de choisir pour chaque propriété, laquelle il doit prendre. + /// Cette méthode utilise les données originales, courantes et en base (cf. exemple 042_016). + /// + /// Deux méthodes sont proposées pour cela : + /// - (METHODE 1) : la première consiste à dédier une colonne pour les vérifications (update et delete) qu'on appelle généralement RowVersion et qu'on décore avec l'attribut Timestamp (cf. classe Nounours) + /// - la seconde permet de ne pas rajouter de colonne spécifique mais de préciser quelles seront les colonnes à utiliser pour les tests de vérification + /// - (METHODE 2a) : soit en annotation de données ([ConcurrencyCheck()]) (cf. classe Nounours) + /// - (METHODE 2b) : soit en fluent API (modelBuilder.Entity().Property(n => n.NbPoils).IsConcurrencyToken();) (cf. classe NounoursDBEntities) + /// + /// Attention de bien noter que la méthode UpdateNounours a été modifiée pour catcher l'exception DbUpdateConcurrencyException et utiliser CurrentValues, OriginalValues et DatabaseValues en cas d'exception. + /// + /// Commentez et décommentez les méthodes pour tester les différentes possibilités + /// + class Program + { + /// + /// récupère un Nounours à partir de son id + /// + /// l'id du Nounours à récupérer + /// le Nounours récupéré (null, si l'id n'est pas connu dans la base) + static Nounours GetNounours(Guid id) + { + Nounours nounours = null; + + using (NounoursDBEntities db = new NounoursDBEntities()) + { + nounours = db.NounoursSet.Single(n => n.UniqueId == id); + } + + return nounours; + } + + /// + /// mise à jour du Nounours dans la base + /// + /// nounours à mettre à jour + static void UpdateNounours(Nounours nounours) + { + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.NounoursSet.Attach(nounours); + db.Entry(nounours).State = EntityState.Modified; + + try + { + db.SaveChanges(); + } + catch (DbUpdateConcurrencyException ex) + { + //observez en mode debug de quelle manière la variable nounours est affectée + //récupération de l'entry + var entry = ex.Entries.Single(); + // Using a NoTracking query means we get the entity but it is not tracked by the context + // and will not be merged with existing entities in the context. + var databaseEntity = db.NounoursSet.AsNoTracking().Single(n => n.UniqueId== (entry.Entity as Nounours).UniqueId); + var databaseEntry = db.Entry(databaseEntity); + + //demande à l'utilisateur de choisir quelles valeurs utiliser : celles modifiées, ou celles actuellement en base + UserChoose(entry, databaseEntry); + + //on applique les données courantes en base + db.SaveChanges(); + + } + } + } + + /// + /// demande à l'utilisateur de choisir entre les données courantes et les données en base de données à l'utilisateur + /// + /// données courantes de l'entité en cours de modification + /// données en base de l'entité en cours de modification + /// données résolues, i.e. choisies par l'utilisateur + private static void UserChoose(EntityEntry entry, EntityEntry databaseEntry) + { + WriteLine("Les données de l'entité que vous souhaitez modifier ont les valeurs suivantes en base (database values) :"); + foreach (var property in entry.Metadata.GetProperties()) + { + WriteLine($"\t{property.Name}: {databaseEntry.Property(property.Name).CurrentValue}"); + } + + WriteLine("Les données de l'entité que vous voulez modifier sont les suivantes (current values) :"); + foreach (var property in entry.Metadata.GetProperties()) + { + WriteLine($"\t{property.Name}: {entry.Property(property.Name).CurrentValue}"); + } + + foreach (var property in entry.Metadata.GetProperties()) + { + var proposedValue = entry.Property(property.Name).CurrentValue; + //var originalValue = entry.Property(property.Name).OriginalValue; + var databaseValue = databaseEntry.Property(property.Name).CurrentValue; + + if (!proposedValue.Equals(databaseValue)) + { + WriteLine($"Que choisissez-vous de garder pour la propriété {property.Name} ? {proposedValue} (tapez c) ; {databaseValue} (tapez d)"); + string réponse = ReadLine(); + switch (réponse) + { + case "c": + WriteLine("Vous avez choisi de garder la valeur courante"); + //met à jour les données courantes avec les données résolues + entry.Property(property.Name).CurrentValue = proposedValue; + break; + case "d": + WriteLine("Vous avez choisi de garder la valeur en base"); + //met à jour les données courantes avec les données en base + entry.Property(property.Name).CurrentValue = databaseValue; + break; + default: + WriteLine("commande non reconnue, par défaut, on garde la donnée en base"); + goto case "d"; + } + //on change les données OriginalValues en les écrasant avec celles en base. + //Ainsi, EF ne voit pas de différences entre les données récupérées en base avant et après les modifications, et croit qu'on peut faire une modification avec CurrentValues + entry.Property(property.Name).OriginalValue = databaseEntry.Property(property.Name).CurrentValue; + } + } + } + + static void Main(string[] args) + { + List ids = new List(); + + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (NounoursDBEntities db = new NounoursDBEntities()) + { + DbContextInitializer.Seed(db); + + //récupère la liste des ids + ids = db.NounoursSet.Select(n => n.UniqueId).ToList(); + } + + PrintTable("Au démarrage, la table contient :"); + + WriteLine(); + + //DEBUT DE LA SIMULATION DE MISES A JOUR CONCURRENTES + + //1. Le premier utilisateur récupère les données du premier nounours + Nounours nounours1 = GetNounours(ids[0]); + WriteLine("L'utilisateur 1 récupère le premier nounours"); + + //2. Le deuxième utilisateur réupère les données du premier nounours + Nounours nounours2 = GetNounours(ids[0]); + WriteLine("L'utilisateur 2 récupère le premier nounours"); + + //jusque-là, la table contient : + // "Chewbacca", 27/05/1977, 1234567 poils + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //3. Le premier utilisateur tente de mettre à jour le nombre de poils, mais ne met pas tout de suite la table à jour + nounours1.NbPoils = 2; + + WriteLine("Soudain, la table est modifiée par des facteurs extérieurs... (un recommandé peut-être...)"); + //4. La table est mise à jour par un autre biais + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.Database.ExecuteSqlCommand($"UPDATE dbo.TableNounours SET NbPoils = 5 WHERE UniqueId = {ids[0]}"); + db.SaveChanges(); + } + PrintTable("Maintenant, la table contient :"); + //maintenant, la table contient : + // "Chewbacca", 27/05/1977, 5 poils <========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //5. L'utilisateur 1 tente de mettre à jour le nombre de poils + UpdateNounours(nounours1); + PrintTable("Après la tentative de modification du nombre de poils de Chewbacca à 2 par l'utilisateur 1 :"); + //une exception est lancée. + //*A vous de choisir si vous voulez utiliser le nombre de poils en base, ou celui rentré par l'utilisateur 1. + //Les autres propriétés n'ont pas changé + + //si vous choisissez de donner votre préférence au choix de l'utilisateur 1, la table contient : + // "Chewbacca", 27/05/1977, 2 poils <========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //6. Le deuxième utilisateur tente de mettre à jour la propriété Date De Naissance + nounours2.DateDeNaissance = DateTime.Today; + UpdateNounours(nounours2); + PrintTable("Après la tentative de modification de la date de naissance de Chewbacca à aujourd'hui par l'utilisateur 2 :"); + //une exception est lancée. + //deux propriétés sont différentes : la date de naissance car l'utilisateur 2 tente de la modifier, le nombre de poils car il a changé entre temps. + //choisissez par exemple de garder la proposition de l'utilisateur 2 pour la date de naissance et la donnée en base pour le nombre de poils + + //si vous respectez ce choix, la table contiendra : + // "Chewbacca", 10/11/2016, 2 poils <========================= + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + } + + static void PrintTable(string intro) + { + WriteLine(); + WriteLine(intro); + using (NounoursDBEntities db = new NounoursDBEntities()) + { + //affiche les nounours après les modifications + WriteLine("Après modifications"); + foreach (var n in db.NounoursSet) + { + WriteLine($"\t{n}"); + } + } + } + } +} diff --git a/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/ex_042_020_EF_concurrency_customDbProp.csproj b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/ex_042_020_EF_concurrency_customDbProp.csproj new file mode 100644 index 0000000..df2de6f --- /dev/null +++ b/p07_Persistance/ex_042_020_EF_concurrency_customDbProp/ex_042_020_EF_concurrency_customDbProp.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_020_EF_concurrency_customDbProp + Exe + ex_042_020_EF_concurrency_customDbProp + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p07_Persistance/ex_042_021_EF_concurrency_customObjects/DbContextInitializer.cs b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/DbContextInitializer.cs new file mode 100644 index 0000000..863195a --- /dev/null +++ b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/DbContextInitializer.cs @@ -0,0 +1,70 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : DbContextInitializer.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-13 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_021_EF_concurrency_customObjects +{ + /// + /// initialiseur de stratégies... + /// + static class DbContextInitializer + { + /// + /// remplissage de la base avec des données stubbées. + /// + /// base à remplir + public static void Seed(NounoursDBEntities context) + { + SetInitializer(context, InitializationStrategies.DropCreateDatabaseAlways); + + Nounours chewie = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 }; + Nounours yoda = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 }; + Nounours ewok = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 }; + + context.NounoursSet.AddRange(new Nounours[] { chewie, yoda, ewok }); + + context.SaveChanges(); + } + + /// + /// les différentes stratégies de création de la base + /// + public enum InitializationStrategies + { + CreateDatabaseIfNotExists, + DropCreateDatabaseIfModelChanges, + DropCreateDatabaseAlways + } + public static void SetInitializer(DbContext context, InitializationStrategies strategy) + { + switch (strategy) + { + //par défaut : crée la base seulement si elle n'existe pas + default: + case InitializationStrategies.CreateDatabaseIfNotExists: + context.Database.EnsureCreated(); + break; + + //recrée la base même si elle existe déjà + case InitializationStrategies.DropCreateDatabaseAlways: + context.Database.EnsureDeleted(); + context.Database.EnsureCreated(); + break; + + //recrée la base seulement si le modèle change : impossible aujourd'hui en Entity Framework Core... + case InitializationStrategies.DropCreateDatabaseIfModelChanges: + throw new NotImplementedException("Le mode DropCreateDatabaseIfModelChanges ne peut pas encore exister sous Entity Framework Core"); + } + } + } +} diff --git a/p07_Persistance/ex_042_021_EF_concurrency_customObjects/Nounours.cs b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/Nounours.cs new file mode 100644 index 0000000..ddede02 --- /dev/null +++ b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/Nounours.cs @@ -0,0 +1,111 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Nounours.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-13 +// +// ======================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_021_EF_concurrency_customObjects +{ + /// + /// Nounours est une classe POCO, i.e. Plain Old CLR Object. + /// + [Table("TableNounours")] + public class Nounours + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + [Required] + [MaxLength(256)] + public string Nom + { + get; + set; + } + + [Column("Naissance")] + //METHODE 2a : + //On ajoute un décorateur sur les propriétés DateDeNaissance et NbPoils (par exemple) + [ConcurrencyCheck] + //FIN METHODE 2a + public DateTime DateDeNaissance + { + get; + set; + } + + //METHODE 2a : + //On ajoute un décorateur sur les propriétés DateDeNaissance et NbPoils (par exemple) + [ConcurrencyCheck] + //FIN METHODE 2a + public int NbPoils + { + get; + set; + } + + /// + /// returns a hash code in order to use this class in hash table + /// + /// hash code + public override int GetHashCode() + { + return Nom.GetHashCode(); + } + + /// + /// checks if the "right" object is equal to this Nounours or not + /// + /// the other object to be compared with this Nounours + /// true if equals, false if not + public override bool Equals(object right) + { + //check null + if (object.ReferenceEquals(right, null)) + { + return false; + } + + if (object.ReferenceEquals(this, right)) + { + return true; + } + + if (this.GetType() != right.GetType()) + { + return false; + } + + return this.Equals(right as Nounours); + } + + /// + /// checks if this Nounours is equal to the other Nounours + /// + /// the other Nounours to be compared with + /// true if equals + public bool Equals(Nounours other) + { + return (this.Nom.Equals(other.Nom) && this.DateDeNaissance == other.DateDeNaissance); + } + + public override string ToString() + { + return $"{UniqueId}: {Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils)"; + } + + } +} diff --git a/p07_Persistance/ex_042_021_EF_concurrency_customObjects/NounoursDBEntities.cs b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/NounoursDBEntities.cs new file mode 100644 index 0000000..245cf49 --- /dev/null +++ b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/NounoursDBEntities.cs @@ -0,0 +1,41 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : NounoursDBEntities.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-13 +// +// ======================================================================== + +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_021_EF_concurrency_customObjects +{ + /// + /// La classe qui dérive de DbContext est celle qui permettra de faire les opérations CRUD sur le modèle. + /// Cette classe contient un DbSet pour permettre de réaliser des opérations CRUD sur le type T, ici Nounours. + /// + class NounoursDBEntities : DbContext + { + public virtual DbSet NounoursSet { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=ex_042_021_EF_concurrency_customObjects.Nounours.mdf;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + ////METHODE 2b + ////On précise que NbPoils et DateDeNaissance sont utilisés pour les tests de vérification de modifications ou suppressions concurrentes. + //modelBuilder.Entity().Property(n => n.NbPoils).IsConcurrencyToken(); + //modelBuilder.Entity().Property(n => n.DateDeNaissance).IsConcurrencyToken(); + ////FIN METHODE 2b + + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/p07_Persistance/ex_042_021_EF_concurrency_customObjects/Program.cs b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/Program.cs new file mode 100644 index 0000000..8baeb9c --- /dev/null +++ b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/Program.cs @@ -0,0 +1,244 @@ +// ======================================================================== +// +// Copyright (C) 2016-2017 MARC CHEVALDONNE +// marc.chevaldonne.free.fr +// +// Module : Program.cs +// Author : Marc Chevaldonné +// Creation date : 2016-11-13 +// +// ======================================================================== + +using static System.Console; +using System.Linq; +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking; +using System.Reflection; + +namespace ex_042_021_EF_concurrency_customObjects +{ + /// + /// Cet exemple simule des mises à jours concurrentes de données dans la table. + /// Contrairement à l'exemple 042_017, il montre comment il est possible de gérer facilement ces insertions concurrentes avec EntityFramework. + /// Contrairement aux exemples 042_018 et 042_019, il ne laisse pas la priorité à la base de données ou au client, mais demande à l'utilisateur de choisir pour chaque propriété, laquelle il doit prendre. + /// Cette méthode utilise les données originales, courantes et en base (cf. exemple 042_016). + /// Elle utilise également les données des Entries proposées par Entity Framework, mais contrairement à l'exemple précédent (042_020), elle les transforme en instances de Nounours. + /// Elle utilise donc les instances de Nounours, et simule un cas ou ce serait à la vue de permettre à l'utilisateur de comparer les objets, sans que celle-ci soit dépendante d'Entity Framework. + /// + /// Deux méthodes sont proposées pour cela : + /// - (METHODE 1) : la première consiste à dédier une colonne pour les vérifications (update et delete) qu'on appelle généralement RowVersion et qu'on décore avec l'attribut Timestamp (cf. classe Nounours) + /// - la seconde permet de ne pas rajouter de colonne spécifique mais de préciser quelles seront les colonnes à utiliser pour les tests de vérification + /// - (METHODE 2a) : soit en annotation de données ([ConcurrencyCheck()]) (cf. classe Nounours) + /// - (METHODE 2b) : soit en fluent API (modelBuilder.Entity().Property(n => n.NbPoils).IsConcurrencyToken();) (cf. classe NounoursDBEntities) + /// + /// Attention de bien noter que la méthode UpdateNounours a été modifiée pour catcher l'exception DbUpdateConcurrencyException et utiliser CurrentValues, OriginalValues et DatabaseValues en cas d'exception. + /// + /// Commentez et décommentez les méthodes pour tester les différentes possibilités + /// + class Program + { + /// + /// récupère un Nounours à partir de son id + /// + /// l'id du Nounours à récupérer + /// le Nounours récupéré (null, si l'id n'est pas connu dans la base) + static Nounours GetNounours(Guid id) + { + Nounours nounours = null; + + using (NounoursDBEntities db = new NounoursDBEntities()) + { + nounours = db.NounoursSet.Single(n => n.UniqueId == id); + } + + return nounours; + } + + /// + /// mise à jour du Nounours dans la base + /// + /// nounours à mettre à jour + static void UpdateNounours(Nounours nounours) + { + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.NounoursSet.Attach(nounours); + db.Entry(nounours).State = EntityState.Modified; + + try + { + db.SaveChanges(); + } + catch (DbUpdateConcurrencyException ex) + { + //observez en mode debug de quelle manière la variable nounours est affectée + //récupération de l'entry + var entry = ex.Entries.Single(); + // Using a NoTracking query means we get the entity but it is not tracked by the context + // and will not be merged with existing entities in the context. + var databaseEntity = db.NounoursSet.AsNoTracking().Single(n => n.UniqueId== (entry.Entity as Nounours).UniqueId); + var databaseEntry = db.Entry(databaseEntity); + + Nounours resolvedNounours; + //demande à l'utilisateur de choisir quelles valeurs utiliser : celles modifiées, ou celles actuellement en base + UserChoose(entry.Entity as Nounours, databaseEntity, out resolvedNounours); + + //parcourt les propriétés et met à jour l'entité traquée et l'entité originale + Type nounoursType = typeof(Nounours); + var properties = nounoursType.GetProperties().Where(p => p.CanRead && p.CanWrite).ToList(); + foreach (var prop in properties) + { + //on change les données courantes avec les données choisies par l'utilisateur + entry.Property(prop.Name).CurrentValue = prop.GetValue(resolvedNounours); + //on change les données OriginalValues en les écrasant avec celles en base. + //Ainsi, EF ne voit pas de différences entre les données récupérées en base avant et après les modifications, et croit qu'on peut faire une modification avec CurrentValues + entry.Property(prop.Name).OriginalValue = databaseEntry.Property(prop.Name).CurrentValue; + } + + + + //on applique les données courantes en base + db.SaveChanges(); + + } + } + } + + /// + /// demande à l'utilisateur de choisir entre les données courantes et les données en base de données à l'utilisateur + /// + /// données courantes de l'entité en cours de modification + /// données en base de l'entité en cours de modification + /// données résolues, i.e. choisies par l'utilisateur + private static void UserChoose(Nounours currentValuesAsNounours, Nounours databaseValuesAsNounours, out Nounours resolvedNounours) + { + resolvedNounours = new Nounours() { UniqueId = databaseValuesAsNounours.UniqueId, Nom = databaseValuesAsNounours.Nom, NbPoils = databaseValuesAsNounours.NbPoils, DateDeNaissance = databaseValuesAsNounours.DateDeNaissance }; + Type nounoursType = typeof(Nounours); + var properties = nounoursType.GetProperties().Where(p => p.CanRead && p.CanWrite).ToList(); + WriteLine("Les données de l'entité que vous souhaitez modifier ont les valeurs suivantes en base (database values) :"); + foreach (var prop in properties) + { + WriteLine($"\t{prop.Name}: {prop.GetValue(databaseValuesAsNounours)}"); + } + + WriteLine("Les données de l'entité que vous voulez modifier sont les suivantes (current values) :"); + foreach (var prop in properties) + { + WriteLine($"\t{prop.Name}: {prop.GetValue(currentValuesAsNounours)}"); + } + + foreach (var prop in properties) + { + if (!prop.GetValue(currentValuesAsNounours).Equals(prop.GetValue(databaseValuesAsNounours))) + { + WriteLine($"Que choisissez-vous de garder pour la propriété {prop.Name} ? {prop.GetValue(currentValuesAsNounours)} (tapez c) ; {prop.GetValue(databaseValuesAsNounours)} (tapez d)"); + string réponse = ReadLine(); + switch (réponse) + { + case "c": + WriteLine("Vous avez choisi de garder la valeur courante"); + prop.SetValue(resolvedNounours, prop.GetValue(currentValuesAsNounours)); + break; + case "d": + WriteLine("Vous avez choisi de garder la valeur en base"); + prop.SetValue(resolvedNounours, prop.GetValue(databaseValuesAsNounours)); + break; + default: + WriteLine("commande non reconnue, par défaut, on garde la donnée en base"); + goto case "d"; + } + } + } + } + static void Main(string[] args) + { + List ids = new List(); + + //création du DbContext et injection de la dépendance à MyStubDataInitializationStrategy + using (NounoursDBEntities db = new NounoursDBEntities()) + { + DbContextInitializer.Seed(db); + + //récupère la liste des ids + ids = db.NounoursSet.Select(n => n.UniqueId).ToList(); + } + + PrintTable("Au démarrage, la table contient :"); + + WriteLine(); + + //DEBUT DE LA SIMULATION DE MISES A JOUR CONCURRENTES + + //1. Le premier utilisateur récupère les données du premier nounours + Nounours nounours1 = GetNounours(ids[0]); + WriteLine("L'utilisateur 1 récupère le premier nounours"); + + //2. Le deuxième utilisateur réupère les données du premier nounours + Nounours nounours2 = GetNounours(ids[0]); + WriteLine("L'utilisateur 2 récupère le premier nounours"); + + //jusque-là, la table contient : + // "Chewbacca", 27/05/1977, 1234567 poils + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //3. Le premier utilisateur tente de mettre à jour le nombre de poils, mais ne met pas tout de suite la table à jour + nounours1.NbPoils = 2; + + WriteLine("Soudain, la table est modifiée par des facteurs extérieurs... (un recommandé peut-être...)"); + //4. La table est mise à jour par un autre biais + using (NounoursDBEntities db = new NounoursDBEntities()) + { + db.Database.ExecuteSqlCommand($"UPDATE dbo.TableNounours SET NbPoils = 5 WHERE UniqueId = {ids[0]}"); + db.SaveChanges(); + } + PrintTable("Maintenant, la table contient :"); + //maintenant, la table contient : + // "Chewbacca", 27/05/1977, 5 poils <========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //5. L'utilisateur 1 tente de mettre à jour le nombre de poils + UpdateNounours(nounours1); + PrintTable("Après la tentative de modification du nombre de poils de Chewbacca à 2 par l'utilisateur 1 :"); + //une exception est lancée. + //*A vous de choisir si vous voulez utiliser le nombre de poils en base, ou celui rentré par l'utilisateur 1. + //Les autres propriétés n'ont pas changé + + //si vous choisissez de donner votre préférence au choix de l'utilisateur 1, la table contient : + // "Chewbacca", 27/05/1977, 2 poils <========================== + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + + //6. Le deuxième utilisateur tente de mettre à jour la propriété Date De Naissance + nounours2.DateDeNaissance = DateTime.Today; + UpdateNounours(nounours2); + PrintTable("Après la tentative de modification de la date de naissance de Chewbacca à aujourd'hui par l'utilisateur 2 :"); + //une exception est lancée. + //deux propriétés sont différentes : la date de naissance car l'utilisateur 2 tente de la modifier, le nombre de poils car il a changé entre temps. + //choisissez par exemple de garder la proposition de l'utilisateur 2 pour la date de naissance et la donnée en base pour le nombre de poils + + //si vous respectez ce choix, la table contiendra : + // "Chewbacca", 10/11/2016, 2 poils <========================= + // "Yoda", 21/05/1980, 3 poils + // "Ewok", 25/05/1983, 3456789 poils + } + + static void PrintTable(string intro) + { + WriteLine(); + WriteLine(intro); + using (NounoursDBEntities db = new NounoursDBEntities()) + { + //affiche les nounours après les modifications + WriteLine("Après modifications"); + foreach (var n in db.NounoursSet) + { + WriteLine($"\t{n}"); + } + } + } + } +} diff --git a/p07_Persistance/ex_042_021_EF_concurrency_customObjects/ex_042_021_EF_concurrency_customObjects.csproj b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/ex_042_021_EF_concurrency_customObjects.csproj new file mode 100644 index 0000000..efc85a6 --- /dev/null +++ b/p07_Persistance/ex_042_021_EF_concurrency_customObjects/ex_042_021_EF_concurrency_customObjects.csproj @@ -0,0 +1,22 @@ + + + net6.0 + ex_042_021_EF_concurrency_customObjects + Exe + ex_042_021_EF_concurrency_customObjects + 6.0.6 + false + false + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/p09_Concurrency_Asynchrony/ex_050_001_CreatingAThread/Program.cs b/p09_Concurrency_Asynchrony/ex_050_001_CreatingAThread/Program.cs new file mode 100644 index 0000000..4f9c484 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_001_CreatingAThread/Program.cs @@ -0,0 +1,38 @@ +using System; +using System.Threading; + +namespace ex_050_001_CreatingAThread +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("main thread affiche cent 1"); + Console.WriteLine("\"petit thread\" affiche deux cents 0"); + + //crée un thread + Thread thread = new Thread(Write0); + //donner un nom au thread est optionnel mais peut faciliter le débogage + thread.Name = "petit thread"; + + Console.WriteLine("\"petit thread\" démarre"); + //lance le thread + thread.Start(); + //le code suivant s'exécute en parallèle de Write0 + + for (int i = 0; i < 100; i++) + { + Console.Write("1"); Console.Beep(12000, 10); + } + } + + //méthode qui va être exécutée en parallèle + static void Write0() + { + for (int i = 0; i < 200; i++) + { + Console.Write("0"); Console.Beep(16000, 10); + } + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_001_CreatingAThread/ex_050_001_CreatingAThread.csproj b/p09_Concurrency_Asynchrony/ex_050_001_CreatingAThread/ex_050_001_CreatingAThread.csproj new file mode 100644 index 0000000..7d6c447 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_001_CreatingAThread/ex_050_001_CreatingAThread.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_001_CreatingAThread + Exe + ex_050_001_CreatingAThread + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_002_attendre_un_thread/Program.cs b/p09_Concurrency_Asynchrony/ex_050_002_attendre_un_thread/Program.cs new file mode 100644 index 0000000..7faf7a2 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_002_attendre_un_thread/Program.cs @@ -0,0 +1,81 @@ +using System; +using System.Threading; + +namespace ex_050_002_attendre_un_thread +{ + class Program + { + static Thread petitThread; + static Thread petitThread2; + + static void Main(string[] args) + { + Console.WriteLine("\"petit thread\" joue un son pendant 2 secondes,"); + Console.WriteLine("\tpuis attend la fin de \"petit thread 2\","); + Console.WriteLine("\tpuis affiche PETIT THREAD"); + Console.WriteLine("\"petit thread 2\" joue un son pendant 3 secondes,"); + Console.WriteLine("\tpuis affiche PETIT THREAD 2"); + Console.WriteLine("le thread principal lance les deux petits threads,"); + Console.WriteLine("\taffiche leur état,"); + Console.WriteLine("\tpuis attend 2,5 secondes"); + Console.WriteLine("\taffiche leur état,"); + Console.WriteLine("\tpuis attend les deux petits threads"); + Console.WriteLine("\tet affiche une dernière fois leur état,"); + + //crée deux threads + petitThread = new Thread(Wait2000); + petitThread2 = new Thread(Wait3000); + //donner un nom au thread est optionnel mais peut faciliter le débogage + petitThread.Name = "petit thread"; + petitThread2.Name = "petit thread 2"; + + PrintThreadsState(petitThread, petitThread2); + + Console.WriteLine("\"petit thread\" et \"petit thread 2\" démarrent"); + //lance les threads + petitThread.Start(); + petitThread2.Start(); + //le code suivant s'exécute en parallèle de Write0 + + PrintThreadsState(petitThread, petitThread2); + + Thread.Sleep(2500); + Console.WriteLine("2,5 secondes se sont écoulées."); + Console.WriteLine("\"petit thread\" est en attente, état : WaitSleepJoin"); + Console.WriteLine("\"petit thread 2\" est en cours d'exécution, état : Running"); + + PrintThreadsState(petitThread, petitThread2); + + petitThread.Join(); + petitThread2.Join(); + + PrintThreadsState(petitThread, petitThread2); + } + + //méthode qui va être exécutée en parallèle + static void Wait2000() + { + Console.Beep(26000, 2000); + petitThread2.Join(); + Console.WriteLine("PETIT THREAD"); + } + + //méthode qui va être exécutée en parallèle + static void Wait3000() + { + Console.Beep(26000, 3000); + Console.WriteLine("PETIT THREAD 2"); + } + + static void PrintThreadsState(params Thread[] threads) + { + Console.WriteLine(); + Console.WriteLine("état des threads:"); + foreach (Thread thread in threads) + { + Console.WriteLine("\t{0} : {1}", thread.Name, thread.ThreadState); + } + Console.WriteLine(); + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_002_attendre_un_thread/ex_050_002_attendre_un_thread.csproj b/p09_Concurrency_Asynchrony/ex_050_002_attendre_un_thread/ex_050_002_attendre_un_thread.csproj new file mode 100644 index 0000000..4e82696 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_002_attendre_un_thread/ex_050_002_attendre_un_thread.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_002_attendre_un_thread + Exe + ex_050_002_attendre_un_thread + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_003_Variables_locales_et_partagées_entre_threads/Program.cs b/p09_Concurrency_Asynchrony/ex_050_003_Variables_locales_et_partagées_entre_threads/Program.cs new file mode 100644 index 0000000..d6dbf21 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_003_Variables_locales_et_partagées_entre_threads/Program.cs @@ -0,0 +1,133 @@ +using System; +using System.Threading; + +namespace ex_050_003_Variables_locales_et_partagées_entre_threads +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("TEST 1 : utilisation d'une variable locale"); + Console.WriteLine("2 threads lancent une même méthode, initialisant une variable locale à la méthode à false"); + Console.WriteLine("affichant sa valeur, puis la passant à true."); + Console.WriteLine("On lance le premier thread 1 seconde avant le 2ème."); + Console.WriteLine("On peut voir ci-dessous que les variables locales ne sont pas partagées"); + + Thread thread1 = new Thread(Test.MéthodeAvecVariableLocale) { Name = "thread1" }; + thread1.Start(); + Thread.Sleep(1000); + + Thread thread2 = new Thread(Test.MéthodeAvecVariableLocale) { Name = "thread2" }; + thread2.Start(); + + thread1.Join(); + thread2.Join(); + + Console.WriteLine("Appuyez sur une touche pour continuer"); + Console.ReadLine(); + + Console.Clear(); + Console.WriteLine("TEST 2 : utilisation d'une seule variable statique"); + Console.WriteLine("2 threads lancent une même méthode statique,"); + Console.WriteLine("affichant la valeur d'un membre statique, puis le passant à true s'il vaut false."); + Console.WriteLine("On lance le premier thread 1 seconde avant le 2ème."); + Console.WriteLine("On peut voir ci-dessous que les variables statiques sont partagées entre les threads."); + + thread1 = new Thread(Test.MéthodeAvecVariablePartagée) { Name = "thread1" }; + thread1.Start(); + Thread.Sleep(1000); + + thread2 = new Thread(Test.MéthodeAvecVariablePartagée) { Name = "thread2" }; + thread2.Start(); + + thread1.Join(); + thread2.Join(); + + Console.WriteLine("Appuyez sur une touche pour continuer"); + Console.ReadLine(); + + Console.Clear(); + Console.WriteLine("TEST 3 : utilisation de deux instances d'une classe utilisant un membre d'instance"); + Console.WriteLine("2 threads lancent une même méthode d'instance, mais à partir de deux instances différentes."); + Console.WriteLine("Cette méthode affiche la valeur d'un membre d'instance, puis le passe à true s'il vaut false."); + Console.WriteLine("On lance le premier thread 1 seconde avant le 2ème."); + Console.WriteLine("On peut voir ci-dessous que les variables d'instance ne sont pas partagées entre les threads, si les instances sont différentes."); + + Test test = new Test(); + thread1 = new Thread(test.MéthodeAvecMembreDInstance) { Name = "thread1" }; + thread1.Start(); + Thread.Sleep(1000); + + Test test2 = new Test(); + thread2 = new Thread(test2.MéthodeAvecMembreDInstance) { Name = "thread2" }; + thread2.Start(); + + thread1.Join(); + thread2.Join(); + + Console.WriteLine("Appuyez sur une touche pour continuer"); + Console.ReadLine(); + + Console.Clear(); + Console.WriteLine("TEST 4 : utilisation d'une seule instance d'une classe utilisant un membre d'instance"); + Console.WriteLine("2 threads lancent une même méthode d'instance, mais à partir d'une seule instance."); + Console.WriteLine("Cette méthode affiche la valeur d'un membre d'instance, puis le passe à true s'il vaut false."); + Console.WriteLine("On lance le premier thread 1 seconde avant le 2ème."); + Console.WriteLine("On peut voir ci-dessous que les variables d'instance sont partagées entre les threads, si l'instance est partagée."); + + Test test3 = new Test(); + thread1 = new Thread(test3.MéthodeAvecMembreDInstance) { Name = "thread1" }; + thread1.Start(); + Thread.Sleep(1000); + + thread2 = new Thread(test3.MéthodeAvecMembreDInstance) { Name = "thread2" }; + thread2.Start(); + + thread1.Join(); + thread2.Join(); + } + } + + class Test + { + //méthode utilisée pour le TEST 1 + public static void MéthodeAvecVariableLocale() + { + bool localTest = false; + Console.WriteLine("test ({0}) = {1}", Thread.CurrentThread.Name, localTest); + if (!localTest) + { + localTest = true; + } + Thread.Sleep(1200); + } + + //membre statique utilisé pour le TEST 2 + static bool staticTest = false; + + //méthode utilisée pour le TEST 2 + public static void MéthodeAvecVariablePartagée() + { + Console.WriteLine("staticTest ({0}) = {1}", Thread.CurrentThread.Name, staticTest); + if (!staticTest) + { + staticTest = true; + } + Thread.Sleep(1200); + } + + //membre d'instance utilisé pour les tests TEST 3 et TEST 4 + bool instanceTest = false; + + //méthode utilisée pour les tests TEST 3 et TEST 4 + public void MéthodeAvecMembreDInstance() + { + Console.WriteLine("instanceTest ({0}) = {1}", Thread.CurrentThread.Name, instanceTest); + if (!instanceTest) + { + instanceTest = true; + } + Thread.Sleep(1200); + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_003_Variables_locales_et_partagées_entre_threads/ex_050_003_Variables_locales_et_partagées_entre_threads.csproj b/p09_Concurrency_Asynchrony/ex_050_003_Variables_locales_et_partagées_entre_threads/ex_050_003_Variables_locales_et_partagées_entre_threads.csproj new file mode 100644 index 0000000..13fdf9e --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_003_Variables_locales_et_partagées_entre_threads/ex_050_003_Variables_locales_et_partagées_entre_threads.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_003_Variables_locales_et_partagées_entre_threads + Exe + ex_050_003_Variables_locales_et_partagées_entre_threads + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_004_cadenas_et_sécurité/Program.cs b/p09_Concurrency_Asynchrony/ex_050_004_cadenas_et_sécurité/Program.cs new file mode 100644 index 0000000..9e8e43a --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_004_cadenas_et_sécurité/Program.cs @@ -0,0 +1,94 @@ +using System; +using System.Threading; + +namespace ex_050_004_cadenas_et_sécurité +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("TEST 4 : utilisation d'une seule instance d'une classe utilisant un membre d'instance non protégé"); + Console.WriteLine("2 threads lancent une même méthode d'instance, mais à partir d'une seule instance."); + Console.WriteLine("Cette méthode affiche la valeur d'un membre d'instance, puis le passe à true s'il vaut false."); + Console.WriteLine("On lance les 2 threads en même temps, 10 fois de suite."); + Console.WriteLine("On peut voir ci-dessous que le résultat peut parfois varier :"); + Console.WriteLine("parfois, les deux affichages se font en même temps, avant qu'un des deux threads ait eu le temps de modifier la valeur de instanceTest ;"); + Console.WriteLine("d'autres fois, non."); + + for (int i = 0; i < 10; i++) + { + Test test = new Test(); + Thread thread1 = new Thread(test.MéthodeAvecMembreDInstance) { Name = "thread1" }; + Thread thread2 = new Thread(test.MéthodeAvecMembreDInstance) { Name = "thread2" }; + + thread1.Start(); + thread2.Start(); + + thread1.Join(); + thread2.Join(); + + Console.WriteLine(); + } + + Console.WriteLine("Appuyez sur une touche pour tester avec un cadenas"); + Console.ReadLine(); + + Console.WriteLine("TEST 4b : utilisation d'une seule instance d'une classe utilisant un membre d'instance protégé par un cadenas."); + Console.WriteLine("2 threads lancent une même méthode d'instance, mais à partir d'une seule instance."); + Console.WriteLine("Cette méthode affiche la valeur d'un membre d'instance, puis le passe à true s'il vaut false."); + Console.WriteLine("On lance les 2 threads en même temps, 10 fois de suite."); + Console.WriteLine("On peut voir ci-dessous que le résultat ne varie jamais, car l'utilisation du membre d'instance est protégé par un cadenas."); + + for (int i = 0; i < 10; i++) + { + TestLock test = new TestLock(); + Thread thread1 = new Thread(test.MéthodeAvecMembreDInstance) { Name = "thread1" }; + Thread thread2 = new Thread(test.MéthodeAvecMembreDInstance) { Name = "thread2" }; + + thread1.Start(); + thread2.Start(); + + thread1.Join(); + thread2.Join(); + + Console.WriteLine(); + } + } + } + + class Test + { + bool instanceTest = false; + + public void MéthodeAvecMembreDInstance() + { + Console.WriteLine("instanceTest ({0}) = {1}", Thread.CurrentThread.Name, instanceTest); + if (!instanceTest) + { + instanceTest = true; + } + Thread.Sleep(1200); + } + } + + class TestLock + { + bool instanceTest = false; + + //le cadenas + static readonly object mLocker = new object(); + + public void MéthodeAvecMembreDInstance() + { + lock (mLocker) // on vérouille le cadenas pour éviter que le bloc suivant puisse être exécuté en parallèle + { + Console.WriteLine("instanceTest ({0}) = {1}", Thread.CurrentThread.Name, instanceTest); + if (!instanceTest) + { + instanceTest = true; + } + } + Thread.Sleep(1200); + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_004_cadenas_et_sécurité/ex_050_004_cadenas_et_sécurité.csproj b/p09_Concurrency_Asynchrony/ex_050_004_cadenas_et_sécurité/ex_050_004_cadenas_et_sécurité.csproj new file mode 100644 index 0000000..9dd7da0 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_004_cadenas_et_sécurité/ex_050_004_cadenas_et_sécurité.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_004_cadenas_et_sécurité + Exe + ex_050_004_cadenas_et_sécurité + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_005_passage_de_paramètre/Program.cs b/p09_Concurrency_Asynchrony/ex_050_005_passage_de_paramètre/Program.cs new file mode 100644 index 0000000..8b0ca2f --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_005_passage_de_paramètre/Program.cs @@ -0,0 +1,71 @@ +using System; +using System.Threading; + +namespace ex_XXX_005_passage_de_paramètre +{ + class Program + { + static void AfficheCarréDeObject(object nombre) + { + float nombreFloat = (float)nombre; + Console.WriteLine("{0} ({1})", nombreFloat * nombreFloat, Thread.CurrentThread.Name); + } + + static void AfficheCarréDeFloat(float nombre) + { + Console.WriteLine("{0} ({1})", nombre * nombre, Thread.CurrentThread.Name); + } + + static void Main(string[] args) + { + //passage de paramètre dans un thread + Thread thread = new Thread(AfficheCarréDeObject) { Name = "thread1" }; + thread.Start(3.0f); + //équivalent à (c'est ce qui est reconstruit par le compilateur) : + ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(AfficheCarréDeObject); + thread = new Thread(parameterizedThreadStart) { Name = "thread2" }; + thread.Start(3.0f); + //inconvénients : + //- on ne peut passer qu'un seul paramètre + //- ce paramètre doit obligatoirement être de type object, ce qui implique un cast + + //Depuis C#3, on peut le faire aussi avec une expression lambda, + //ce qui permet de : + //- passer un paramètre typé (pas forcément object) + thread = new Thread(() => AfficheCarréDeFloat(3.0f)) { Name = "thread3" }; + thread.Start(); + //- passer plusieurs paramètres + thread = new Thread(() => AfficheMultiplicationDeFloat(2.0f, 3.0f)) { Name = "thread4" }; + thread.Start(); + + thread.Join(); + Console.WriteLine(); + + //ATTENTION toutefois aux expressions lambda : + //(lancez ce programme plusieurs fois pour bien identifier le problème) + //la sortie n'est pas sûre, car la variable i (son espace mémoire en particulier) + //est utilisée par les 10 threads mais on ne sait pas exactement quand. + //i peut avoir changé (i++) avant que le thread n'ait eu le temps d'appeler la méthode + for (int i = 0; i < 10; i++) + { + thread = new Thread(() => AfficheCarréDeFloat(i)) { Name = "thread5" }; + thread.Start(); + } + thread.Join(); + Console.WriteLine(); + + //la solution consiste à utiliser une variable temporaire qui ne sera pas partagée et ne sera pas modifiée + for (int i = 0; i < 10; i++) + { + int temp = i; + thread = new Thread(() => AfficheCarréDeFloat(temp)) { Name = "thread6" }; + thread.Start(); + } + } + + static void AfficheMultiplicationDeFloat(float nombre1, float nombre2) + { + Console.WriteLine("{0} ({1})", nombre1 * nombre2, Thread.CurrentThread.Name); + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_005_passage_de_paramètre/ex_050_005_passage_de_paramètre.csproj b/p09_Concurrency_Asynchrony/ex_050_005_passage_de_paramètre/ex_050_005_passage_de_paramètre.csproj new file mode 100644 index 0000000..b7db931 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_005_passage_de_paramètre/ex_050_005_passage_de_paramètre.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_005_passage_de_paramètre + Exe + ex_050_005_passage_de_paramètre + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_006_gestion_des_exceptions/Program.cs b/p09_Concurrency_Asynchrony/ex_050_006_gestion_des_exceptions/Program.cs new file mode 100644 index 0000000..a7b5bb3 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_006_gestion_des_exceptions/Program.cs @@ -0,0 +1,45 @@ +using System; +using System.Threading; + +namespace ex_050_006_gestion_des_exceptions +{ + class Program + { + static void DivisionParZéroGérantException() + { + int a = 1, b = 0; + try + { + int c = a / b; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + static void DivisionParZéroNEGérantPASException() + { + int a = 1, b = 0; + int c = a / b; + } + + static void Main(string[] args) + { + //Pour capturer une exception dans une méthode lancée par un thread, + //il faut mettre le try/catch dans la méthode lancée par le thread + new Thread(DivisionParZéroGérantException).Start(); + + //si on tente de capturer l'exception lancée dans un thread secondaire, dans le thread principal, + //l'exception n'est pas attrapée (puisqu'elle est lancée dans un autre thread) + try + { + new Thread(DivisionParZéroNEGérantPASException).Start(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_006_gestion_des_exceptions/ex_050_006_gestion_des_exceptions.csproj b/p09_Concurrency_Asynchrony/ex_050_006_gestion_des_exceptions/ex_050_006_gestion_des_exceptions.csproj new file mode 100644 index 0000000..5705b6c --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_006_gestion_des_exceptions/ex_050_006_gestion_des_exceptions.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_006_gestion_des_exceptions + Exe + ex_050_006_gestion_des_exceptions + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/Program.cs b/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/Program.cs new file mode 100644 index 0000000..15f9653 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/Program.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using System.Threading; + +namespace ex_050_007_Foreground_vs_Background +{ + class Program + { + //le travail que vont faire les 2 threads pendant qu'ils s'exécutent + static void ThreadAtWork(TextWriter tw, int i) + { + Console.WriteLine("{0} ({1})", i, Thread.CurrentThread.Name); + tw.WriteLine("{0} ({1})", i, Thread.CurrentThread.Name); + Thread.Sleep(1); + } + + static void Main(string[] args) + { + //le premier thread affiche 200 fois l'entier i qui est incrémenté suivi du nom du thread entre parenthèses, + //dans la console, et dans un fichier + //La propriété IsBackground n'étant pas initialisée, elle prend la valeur par défaut qui est false + //Ce thread est donc Foreground + Thread threadAvant = new Thread(() => + { + using (TextWriter tw = File.CreateText("avant.txt")) + { + for (int i = 0; i < 200; i++) + { + ThreadAtWork(tw, i); + } + } + }) + { + Name = "foreground thread" + }; + + //le deuxième thread affiche 2000 fois l'entier i qui est incrémenté suivi du nom du thread entre parenthèses, + //dans la console, et dans un fichier + //La propriété IsBackground est initialisée à true + //Ce thread est donc Background + Thread threadArrière = new Thread(() => + { + using (TextWriter tw = File.CreateText("arriere.txt")) + { + for (int i = 0; i < 2000; i++) + { + ThreadAtWork(tw, i); + } + } + }) + { + Name = "background thread", + IsBackground = true + }; + + //Les 2 threads sont lancés et le thread principal est immédiatement terminé + threadAvant.Start(); + threadArrière.Start(); + + //Vous pouvez observer que "foreground thread" est exécuté jusqu'à la fin, + //et que le fichier créé avant.txt est bien écrit et fermé correctement (le bloc using est correctement exécuté jusqu'à la fin). + //Vous pouvez observer que "background thread" n'est pas exécuté jusqu'à la fin (il continue jusqu'à la fin de foreground thread), + //et que le fichier créé arriere.txt n'est pas complétement écrit (le bloc using n'est pas terminé correctement) et Dispose + //n'est donc pas correctement appelé. Si vous voulez vous en assurer, avec un background thread, il faudra l'attendre. + + //Note : les 2 fichiers sont accessibles après exécution dans l'explorateur de solutions, au niveau de ce projet. + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/arriere.txt b/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/arriere.txt new file mode 100644 index 0000000..3cbae9f --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/arriere.txt @@ -0,0 +1,169 @@ +0 (background thread) +1 (background thread) +2 (background thread) +3 (background thread) +4 (background thread) +5 (background thread) +6 (background thread) +7 (background thread) +8 (background thread) +9 (background thread) +10 (background thread) +11 (background thread) +12 (background thread) +13 (background thread) +14 (background thread) +15 (background thread) +16 (background thread) +17 (background thread) +18 (background thread) +19 (background thread) +20 (background thread) +21 (background thread) +22 (background thread) +23 (background thread) +24 (background thread) +25 (background thread) +26 (background thread) +27 (background thread) +28 (background thread) +29 (background thread) +30 (background thread) +31 (background thread) +32 (background thread) +33 (background thread) +34 (background thread) +35 (background thread) +36 (background thread) +37 (background thread) +38 (background thread) +39 (background thread) +40 (background thread) +41 (background thread) +42 (background thread) +43 (background thread) +44 (background thread) +45 (background thread) +46 (background thread) +47 (background thread) +48 (background thread) +49 (background thread) +50 (background thread) +51 (background thread) +52 (background thread) +53 (background thread) +54 (background thread) +55 (background thread) +56 (background thread) +57 (background thread) +58 (background thread) +59 (background thread) +60 (background thread) +61 (background thread) +62 (background thread) +63 (background thread) +64 (background thread) +65 (background thread) +66 (background thread) +67 (background thread) +68 (background thread) +69 (background thread) +70 (background thread) +71 (background thread) +72 (background thread) +73 (background thread) +74 (background thread) +75 (background thread) +76 (background thread) +77 (background thread) +78 (background thread) +79 (background thread) +80 (background thread) +81 (background thread) +82 (background thread) +83 (background thread) +84 (background thread) +85 (background thread) +86 (background thread) +87 (background thread) +88 (background thread) +89 (background thread) +90 (background thread) +91 (background thread) +92 (background thread) +93 (background thread) +94 (background thread) +95 (background thread) +96 (background thread) +97 (background thread) +98 (background thread) +99 (background thread) +100 (background thread) +101 (background thread) +102 (background thread) +103 (background thread) +104 (background thread) +105 (background thread) +106 (background thread) +107 (background thread) +108 (background thread) +109 (background thread) +110 (background thread) +111 (background thread) +112 (background thread) +113 (background thread) +114 (background thread) +115 (background thread) +116 (background thread) +117 (background thread) +118 (background thread) +119 (background thread) +120 (background thread) +121 (background thread) +122 (background thread) +123 (background thread) +124 (background thread) +125 (background thread) +126 (background thread) +127 (background thread) +128 (background thread) +129 (background thread) +130 (background thread) +131 (background thread) +132 (background thread) +133 (background thread) +134 (background thread) +135 (background thread) +136 (background thread) +137 (background thread) +138 (background thread) +139 (background thread) +140 (background thread) +141 (background thread) +142 (background thread) +143 (background thread) +144 (background thread) +145 (background thread) +146 (background thread) +147 (background thread) +148 (background thread) +149 (background thread) +150 (background thread) +151 (background thread) +152 (background thread) +153 (background thread) +154 (background thread) +155 (background thread) +156 (background thread) +157 (background thread) +158 (background thread) +159 (background thread) +160 (background thread) +161 (background thread) +162 (background thread) +163 (background thread) +164 (background thread) +165 (background thread) +166 (background thread) +167 (background thread) +168 (b \ No newline at end of file diff --git a/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/avant.txt b/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/avant.txt new file mode 100644 index 0000000..40e32b3 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/avant.txt @@ -0,0 +1,200 @@ +0 (foreground thread) +1 (foreground thread) +2 (foreground thread) +3 (foreground thread) +4 (foreground thread) +5 (foreground thread) +6 (foreground thread) +7 (foreground thread) +8 (foreground thread) +9 (foreground thread) +10 (foreground thread) +11 (foreground thread) +12 (foreground thread) +13 (foreground thread) +14 (foreground thread) +15 (foreground thread) +16 (foreground thread) +17 (foreground thread) +18 (foreground thread) +19 (foreground thread) +20 (foreground thread) +21 (foreground thread) +22 (foreground thread) +23 (foreground thread) +24 (foreground thread) +25 (foreground thread) +26 (foreground thread) +27 (foreground thread) +28 (foreground thread) +29 (foreground thread) +30 (foreground thread) +31 (foreground thread) +32 (foreground thread) +33 (foreground thread) +34 (foreground thread) +35 (foreground thread) +36 (foreground thread) +37 (foreground thread) +38 (foreground thread) +39 (foreground thread) +40 (foreground thread) +41 (foreground thread) +42 (foreground thread) +43 (foreground thread) +44 (foreground thread) +45 (foreground thread) +46 (foreground thread) +47 (foreground thread) +48 (foreground thread) +49 (foreground thread) +50 (foreground thread) +51 (foreground thread) +52 (foreground thread) +53 (foreground thread) +54 (foreground thread) +55 (foreground thread) +56 (foreground thread) +57 (foreground thread) +58 (foreground thread) +59 (foreground thread) +60 (foreground thread) +61 (foreground thread) +62 (foreground thread) +63 (foreground thread) +64 (foreground thread) +65 (foreground thread) +66 (foreground thread) +67 (foreground thread) +68 (foreground thread) +69 (foreground thread) +70 (foreground thread) +71 (foreground thread) +72 (foreground thread) +73 (foreground thread) +74 (foreground thread) +75 (foreground thread) +76 (foreground thread) +77 (foreground thread) +78 (foreground thread) +79 (foreground thread) +80 (foreground thread) +81 (foreground thread) +82 (foreground thread) +83 (foreground thread) +84 (foreground thread) +85 (foreground thread) +86 (foreground thread) +87 (foreground thread) +88 (foreground thread) +89 (foreground thread) +90 (foreground thread) +91 (foreground thread) +92 (foreground thread) +93 (foreground thread) +94 (foreground thread) +95 (foreground thread) +96 (foreground thread) +97 (foreground thread) +98 (foreground thread) +99 (foreground thread) +100 (foreground thread) +101 (foreground thread) +102 (foreground thread) +103 (foreground thread) +104 (foreground thread) +105 (foreground thread) +106 (foreground thread) +107 (foreground thread) +108 (foreground thread) +109 (foreground thread) +110 (foreground thread) +111 (foreground thread) +112 (foreground thread) +113 (foreground thread) +114 (foreground thread) +115 (foreground thread) +116 (foreground thread) +117 (foreground thread) +118 (foreground thread) +119 (foreground thread) +120 (foreground thread) +121 (foreground thread) +122 (foreground thread) +123 (foreground thread) +124 (foreground thread) +125 (foreground thread) +126 (foreground thread) +127 (foreground thread) +128 (foreground thread) +129 (foreground thread) +130 (foreground thread) +131 (foreground thread) +132 (foreground thread) +133 (foreground thread) +134 (foreground thread) +135 (foreground thread) +136 (foreground thread) +137 (foreground thread) +138 (foreground thread) +139 (foreground thread) +140 (foreground thread) +141 (foreground thread) +142 (foreground thread) +143 (foreground thread) +144 (foreground thread) +145 (foreground thread) +146 (foreground thread) +147 (foreground thread) +148 (foreground thread) +149 (foreground thread) +150 (foreground thread) +151 (foreground thread) +152 (foreground thread) +153 (foreground thread) +154 (foreground thread) +155 (foreground thread) +156 (foreground thread) +157 (foreground thread) +158 (foreground thread) +159 (foreground thread) +160 (foreground thread) +161 (foreground thread) +162 (foreground thread) +163 (foreground thread) +164 (foreground thread) +165 (foreground thread) +166 (foreground thread) +167 (foreground thread) +168 (foreground thread) +169 (foreground thread) +170 (foreground thread) +171 (foreground thread) +172 (foreground thread) +173 (foreground thread) +174 (foreground thread) +175 (foreground thread) +176 (foreground thread) +177 (foreground thread) +178 (foreground thread) +179 (foreground thread) +180 (foreground thread) +181 (foreground thread) +182 (foreground thread) +183 (foreground thread) +184 (foreground thread) +185 (foreground thread) +186 (foreground thread) +187 (foreground thread) +188 (foreground thread) +189 (foreground thread) +190 (foreground thread) +191 (foreground thread) +192 (foreground thread) +193 (foreground thread) +194 (foreground thread) +195 (foreground thread) +196 (foreground thread) +197 (foreground thread) +198 (foreground thread) +199 (foreground thread) diff --git a/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/ex_050_007_Foreground_vs_Background.csproj b/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/ex_050_007_Foreground_vs_Background.csproj new file mode 100644 index 0000000..dfcc6da --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_007_Foreground_vs_Background/ex_050_007_Foreground_vs_Background.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_007_Foreground_vs_Background + Exe + ex_050_007_Foreground_vs_Background + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_008_Priorité/Program.cs b/p09_Concurrency_Asynchrony/ex_050_008_Priorité/Program.cs new file mode 100644 index 0000000..aa40f8e --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_008_Priorité/Program.cs @@ -0,0 +1,35 @@ +using System; +using System.Threading; + +namespace ex_050_008_Priorité +{ + class Program + { + static void Main(string[] args) + { + Thread thread1 = new Thread(() => { for (int i = 0; i < 10000; i++) Console.Write("x"); Console.WriteLine("FIN THREAD1"); }); + Thread thread2 = new Thread(() => { for (int i = 0; i < 10000; i++) Console.Write("y"); Console.WriteLine("FIN THREAD2"); }); + + thread1.Start(); + thread2.Start(); + + thread1.Join(); + thread2.Join(); + + Console.WriteLine(); + Console.WriteLine(); + + thread1 = new Thread(() => { for (int i = 0; i < 10000; i++) Console.Write("x"); Console.WriteLine("FIN THREAD1"); }) + { + Priority = ThreadPriority.Highest + }; + thread2 = new Thread(() => { for (int i = 0; i < 10000; i++) Console.Write("y"); Console.WriteLine("FIN THREAD2"); }) + { + Priority = ThreadPriority.Lowest + }; + + thread1.Start(); + thread2.Start(); + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_008_Priorité/ex_050_008_Priorité.csproj b/p09_Concurrency_Asynchrony/ex_050_008_Priorité/ex_050_008_Priorité.csproj new file mode 100644 index 0000000..35ebe98 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_008_Priorité/ex_050_008_Priorité.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_008_Priorité + Exe + ex_050_008_Priorité + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_009_signalisation/Program.cs b/p09_Concurrency_Asynchrony/ex_050_009_signalisation/Program.cs new file mode 100644 index 0000000..be3ba3a --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_009_signalisation/Program.cs @@ -0,0 +1,83 @@ +using System; +using System.Threading; + +namespace ex_050_009_notifications_entre_threads +{ + class Program + { + static void Main(string[] args) + { + //préparation de deux signaux + var signal = new AutoResetEvent(false); + var signal2 = new AutoResetEvent(false); + + //thread qui joue 4 fois le refrain de la chanson + new Thread(() => + { + for (int i = 0; i < 4; i++) + { + //attend le signal pour écrire le refrain + signal.WaitOne(); + Console.WriteLine("\tUn'jolie fleur dans une peau d'vache"); + Console.WriteLine("\tUn'jolie vach' déguisée en fleur,"); + Console.WriteLine("\tQui fait la belle et qui vous attache,"); + Console.WriteLine("\tPuis, qui vous mèn' par le bout du coeur"); + Console.WriteLine(); + //envoie le signal pour le prochain couplet + signal2.Set(); + } + //nettoyage + signal.Dispose(); + signal2.Dispose(); + }).Start(); + + Console.WriteLine("Jamais sur Terre, il n'y eut d'amoureux"); + Console.WriteLine("Plus aveugles que moi dans tous les âges,"); + Console.WriteLine("Mais faut dir' qu'je m'étais crevé les yeux"); + Console.WriteLine("En regardant de trop près son corsage..."); + Console.WriteLine(); + + //envoie le signal pour le prochain refrain + signal.Set(); + //attend le signal pour écrire le prochain couplet + signal2.WaitOne(); + + Console.WriteLine("Le ciel l'avait pourvu' des mille appâts"); + Console.WriteLine("Qui vous font prendre feu dès qu'on y touche,"); + Console.WriteLine("L'en avait tant que je ne savais pas"); + Console.WriteLine("Ne savais plus où donner de la bouche..."); + Console.WriteLine(); + + //envoie le signal pour le prochain refrain + signal.Set(); + //attend le signal pour écrire le prochain couplet + signal2.WaitOne(); + + Console.WriteLine("Ell'n'avait pa de tête, ell'n'avait pas"); + Console.WriteLine("L'esprit beaucoup plus grand qu'un dé à coudre,"); + Console.WriteLine("Mais pour l'amour on ne demande pas"); + Console.WriteLine("Aux filles d'avoir inventé la poudre..."); + Console.WriteLine(); + + //envoie le signal pour le prochain refrain + signal.Set(); + //attend le signal pour écrire le prochain couplet + signal2.WaitOne(); + + Console.WriteLine("Puis un jour elle a pris la clef des champs"); + Console.WriteLine("En me laissant à l'âme un mal funeste"); + Console.WriteLine("Et toutes les herbes de la Saint-Jean"); + Console.WriteLine("N'ont pas pu me guérir de cette peste..."); + Console.WriteLine(); + + Console.WriteLine("J'lui en ai bien voulu, mais à présent"); + Console.WriteLine("J'ai plus d'rancune et mon coeur lui pardonne"); + Console.WriteLine("D'avoir mis mon coeur à feu et à sang"); + Console.WriteLine("Pour qu'il ne puisse plus servir à personne..."); + Console.WriteLine(); + + //envoie le signal pour le prochain refrain + signal.Set(); + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_009_signalisation/ex_050_009_notifications_entre_threads.csproj b/p09_Concurrency_Asynchrony/ex_050_009_signalisation/ex_050_009_notifications_entre_threads.csproj new file mode 100644 index 0000000..a5bf23d --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_009_signalisation/ex_050_009_notifications_entre_threads.csproj @@ -0,0 +1,12 @@ + + + net6.0 + ex_050_009_notifications_entre_threads + Exe + ex_050_009_notifications_entre_threads + 6.0.6 + false + false + false + + diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/App.xaml b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/App.xaml new file mode 100644 index 0000000..84926cd --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/App.xaml @@ -0,0 +1,7 @@ + + + diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/App.xaml.cs b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/App.xaml.cs new file mode 100644 index 0000000..851ff73 --- /dev/null +++ b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/App.xaml.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +namespace ex_050_010_Threading_en_UWP +{ + /// + /// Fournit un comportement spécifique à l'application afin de compléter la classe Application par défaut. + /// + sealed partial class App : Application + { + /// + /// Initialise l'objet d'application de singleton. Il s'agit de la première ligne du code créé + /// à être exécutée. Elle correspond donc à l'équivalent logique de main() ou WinMain(). + /// + public App() + { + this.InitializeComponent(); + this.Suspending += OnSuspending; + } + + /// + /// Invoqué lorsque l'application est lancée normalement par l'utilisateur final. D'autres points d'entrée + /// seront utilisés par exemple au moment du lancement de l'application pour l'ouverture d'un fichier spécifique. + /// + /// Détails concernant la requête et le processus de lancement. + protected override void OnLaunched(LaunchActivatedEventArgs e) + { + Frame rootFrame = Window.Current.Content as Frame; + + // Ne répétez pas l'initialisation de l'application lorsque la fenêtre comporte déjà du contenu, + // assurez-vous juste que la fenêtre est active + if (rootFrame == null) + { + // Créez un Frame utilisable comme contexte de navigation et naviguez jusqu'à la première page + rootFrame = new Frame(); + + rootFrame.NavigationFailed += OnNavigationFailed; + + if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) + { + //TODO: chargez l'état de l'application précédemment suspendue + } + + // Placez le frame dans la fenêtre active + Window.Current.Content = rootFrame; + } + + if (e.PrelaunchActivated == false) + { + if (rootFrame.Content == null) + { + // Quand la pile de navigation n'est pas restaurée, accédez à la première page, + // puis configurez la nouvelle page en transmettant les informations requises en tant que + // paramètre + rootFrame.Navigate(typeof(MainPage), e.Arguments); + } + // Vérifiez que la fenêtre actuelle est active + Window.Current.Activate(); + } + } + + /// + /// Appelé lorsque la navigation vers une page donnée échoue + /// + /// Frame à l'origine de l'échec de navigation. + /// Détails relatifs à l'échec de navigation + void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new Exception("Failed to load Page " + e.SourcePageType.FullName); + } + + /// + /// Appelé lorsque l'exécution de l'application est suspendue. L'état de l'application est enregistré + /// sans savoir si l'application pourra se fermer ou reprendre sans endommager + /// le contenu de la mémoire. + /// + /// Source de la requête de suspension. + /// Détails de la requête de suspension. + private void OnSuspending(object sender, SuspendingEventArgs e) + { + var deferral = e.SuspendingOperation.GetDeferral(); + //TODO: enregistrez l'état de l'application et arrêtez toute activité en arrière-plan + deferral.Complete(); + } + } +} diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/LockScreenLogo.scale-200.png b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..735f57adb5dfc01886d137b4e493d7e97cf13af3 GIT binary patch literal 1430 zcmaJ>TTC2P7~aKltDttVHYH6u8Io4i*}3fO&d$gd*bA_<3j~&e7%8(eXJLfhS!M@! zKrliY>>6yT4+Kr95$!DoD(Qn-5TP|{V_KS`k~E6(LGS@#`v$hQo&^^BKsw3HIsZBT z_y6C2n`lK@apunKojRQ^(_P}Mgewt$(^BBKCTZ;*xa?J3wQ7~@S0lUvbcLeq1Bg4o zH-bvQi|wt~L7q$~a-gDFP!{&TQfc3fX*6=uHv* zT&1&U(-)L%Xp^djI2?~eBF2cxC@YOP$+9d?P&h?lPy-9M2UT9fg5jKm1t$m#iWE{M zIf%q9@;fyT?0UP>tcw-bLkz;s2LlKl2qeP0w zECS7Ate+Awk|KQ+DOk;fl}Xsy4o^CY=pwq%QAAKKl628_yNPsK>?A>%D8fQG6IgdJ ztnxttBz#NI_a@fk7SU`WtrpsfZsNs9^0(2a z@C3#YO3>k~w7?2hipBf{#b6`}Xw1hlG$yi?;1dDs7k~xDAw@jiI*+tc;t2Lflg&bM)0!Y;0_@=w%`LW^8DsYpS#-bLOklX9r?Ei}TScw|4DbpW%+7 zFgAI)f51s}{y-eWb|vrU-Ya!GuYKP)J7z#*V_k^Xo>4!1Yqj*m)x&0L^tg3GJbVAJ zJ-Pl$R=NAabouV=^z_t;^K*0AvFs!vYU>_<|I^#c?>>CR<(T?=%{;U=aI*SbZADLH z&(f2wz_Y0??Tf|g;?|1Znw6}6U43Q#qNRwv1vp9uFn1)V#*4p&%$mP9x&15^OaBiDS(XppT|z^>;B{PLVEbS3IFYV yGvCsSX*m literal 0 HcmV?d00001 diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/SplashScreen.scale-200.png b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..023e7f1feda78d5100569825acedfd213a0d84e9 GIT binary patch literal 7700 zcmeHLYj~4Yw%(;oxoEH#Kxq-eR|+VkP17b#Vk;?4QwkI+A{L04G+#<<(x#Un1#+h5>eArRq zTw$)ZvTWW_Y?bDho0nPVTh08+s`sp!j74rJTTtXIDww0SILedFv?sZ?yb@@}GN;#8 znk_b~Q(A0YR#uV4ef!osoV1M3;vQ8N$O|fStfgf$S5;ddUNv`tWtGjM;koG#N;7M< zP*84lnx(bn_KF&9Z5Ai$)#Cs3a|$OFw>WKCT$of*L7_CqQEinflT|W{JT+aKp-E0v zsxmYg)1(T>DROm+LN1eQw8}KCTp=C!$H7`PU!t9_Hw@TsTI2`udRZv*!a5`#A9hK6Y95L(CDUX&_@QxKV z_feX{UhA#ZWlvgpL$#w^D#lq`_A4AzDqd|Zv6y9PX&DNcN|l}_D^{q@GG&H^Pg583 z8FI6N8^H7b5WjGp;urW)d7F+_lcp%KsLX0viCmE(OHH+=%ZfD_=`voUuoUxFO^L;- z;!;2{g-YiiO6m4bs89OuF9!p{FGtH-f%8<2gY!h9s)4ciN%{Kh1+`}{^}M~+TDH9N z^Z5PlgVXMC&2&k*Hw^Lb9gny#ro$MOIxIt{+r)EA10$VR3 zanN8D{TUkl+v0CQ_>ZoHP<M-x#8@8ZiT#$Kh`(uRaX1g$Bg|qy$<#7 zSSAi{Nb8Y=lvNVeio+UGLCAtoLBfL`iOv`)yoJMDJBN>4IH@(l7YRF;61@>qq1iM9 zr@b#OC~SAxSle?5Pp8Z78{VO0YFr1x7kZU64Z23eLf2T2#6J_t;-E}DkB?NufZ0Ug zi?J&byXeaB-uTNVhuiM!UVQw}bZrJ3GtAETYp->!{q#zfN7D3AS9@Q7*V^85jGx#R z(QxYV(wW#F0XF9^^s>>H8pPlVJ>)3Oz z&_X8Sf@~?cH_O*cgi$U#`v`RRfv#y3m(ZpKk^5uLup+lVs$~}FZU$r_+}#hl%?g5m z-u-}-666ssp-xWQak~>PPy$mRc|~?pVSs1_@mBEXpPVfLF6(Ktf1S* zPPh@QZ=tFMs?LM2(5P3L2;l_6XX6s&cYsP1ip#eg0`ZEP0HGYh{UmS@o`MihLLvkU zgyAG0G`b1|qjxxh1(ODKFE%AP}Dq=3vK$P7TXP4GrM1kQ72!GUVMDl`rDC&2;TA}*nF z8$nQD&6ys_nc1*E7$*1S@R8$ymy(sQV}imGSedB@{!QR5P&N_H=-^o!?LsWs+2|mH z-e=)T^SvI)=_JIm7}j4;@*Z17=(#}m=~YF~z~CLI+vdAGlJDcdF$TM?CVI1%LhUrN zaa6DJ=Yh$)$k&Oz{-~8yw^GM^8prYxSxo zvI4k#ibryMa%%*8oI-5m61Koa_A_xg=(fwp0aBX{;X4Q;NXUhtaoJDo1>TqhWtn=_ zd5~chq#&6~c%8JZK#t_&J(9EVUU&upYeIovLt1>vaHe}UUq>#RGQj!EN#5+0@T`(@ z^g~>*c`VGRiSt;!$_4+0hk^I!@O3``5=sZ8IwlxWW7km1B&_t&E*u0_9UBa#VqwY* zz>nxv?FAsVnRaD(Bui=6i==BFUw0k4n$>`umU`F2l?7CYTD^)c2X+d9X&ddS9|gj? zM?knGkGCX&W8offw8aLC2$D{PjC3nVZwd4k?eZH8*mZ)U@3Qk8RDFOz_#WUA#vnzy zyP>KrCfKwSXea7}jgJjBc}PGY+4#6%lbZyjhy`5sZd_Vy6Wz;ixa?czkN}J9It1K6 zY!eu>|AwF^fwZlLAYyQI*lM@^>O>Iu6Vf6i>Q$?v!SeUS<{>UYMwz$*%Aq?w^`j{h z!$GZbhu=^D{&ET8;))LL%ZBDZkQqRd2;u~!d9bHGmLRhLDctNgYyjsuvoSZ#iVdoB z2!f--UUA#U;<{je#?cYt^{PIyKa%hW>}uepWMyAI{{Zo7?2>?$c9;whJae%oN|I-kpTQSx_C$Z&;f zi2i)qmEn=y4U0uvk)$m;zKfjPK@oc?I`}1Jzl$Q~aoKBd3kt7L#7gyt|A_qgz6ai< z=X%D1i!d2h?rHR^R8SUj&G||dkC?DT>{o#Yau<@uqVT{Xef&XG}5*E4aPk{}~ zplx&XhaV)&1EfI3Em;Bw#O5SV^c;{twb-1Rw)+=0!e_BLbd7tYmXCH0wrlOSS+~`7He8Iqx0{CN+DVit9;*6L~JAN zD&cyT)2?h}xnYmL?^)<7YyzZ3$FHU^Eg;DLqAV{#wv#Wj7S`Jdl1pX&{3(uZ?!uh} zDc$ZTNV*7le_W6}Hju~GMTxZQ1aWCeUc%!jv3MHAzt>Y-nQK%zfT*3ebDQA5b?iGn; zBjv3B+GhLTexd_(CzZDP4|#n5^~scvB6#Pk%Ho!kQ>yYw((Dv{6=$g3jT1!u6gORW zx5#`7Wy-ZHRa~IxGHdrp(bm%lf>2%J660nj$fCqN(epv@y!l9s7@k6EvxS{AMP>WY zX4$@F8^kayphIx-RGO$+LYl9YdoI5d|4#q9##`_F5Xnx`&GPzp2fB{-{P@ATw=X@~ z_|&^UMWAKD;jjBKTK(~o?cUFRK8EX=6>cXpfzg4ZpMB>*w_^8GSiT-Jp|xBOnzM+j z*09-@-~qJ(eqWq5@R4i^u4^{McCP(!3}C|v_WsTR*bIUxN(Nx`u##3B4{sE`Z`v8w zAwIG`?1~PkID~W{uDzmqH98Pew_1(;x2%8r^vY{)_&J2K)cN{W+h5+g)ZcjP&Ci#O zgy|8K@4kyMfwilHd&6TDlhb%++Pk!>9HRld6HT7gwyZGrxS$}CsD6`>6!!2K1@Mjf z(P0WYB7V_OFZyeWrbOFb>O54BNXf~K&?}3=^v;v_wT{DKr?jN^DtN&DXwX%u?s*c6`%8>WFz z7}YW^tp0bp^NriE)AB6M2l<7rn7fzePtR*omOevpfm9n?}2V*+0iW;S)C zhg`NAjL?D=W#k*$aR{>pGf~lD-rVtD;5jW1_*Jn1j1=es@Kcx4ySM_bwcQCT=d+DV z>Sz~L=Hj@(X%31nK$mWI@7d>}ORB`K(p=+`UD)+99YUGQc7y^bHZ1F(8|tL0 zdK*DT0kSXG_{BKTpP2*2PecdKV9;dq$^ZZDP;Nyq1kp-&GI5eAyZsK!e3V zK@rPy*{(`KIfo+lc878mDKk^V#`VT05}64kBtk%DgwLrOvLMj5-;*GNKv6c6pzMuL z6EP%ob|_0IW}lLRXCP2!9wWhEw3LA7iF#1O1mIZ@Z=6&bz41F;@S_GvYAG-#CW3z{ zP3+6vHhvP&A3$##Vo9$dT^#MoGg^|MDm=Bt1d2RRwSZ<;ZHICpLBv5Xs!D?BH^(9_ z7`H=N&^v|Z-%mP}wNzG{aiFCsRgwzwq!N6obW9+7(R; z(SZ=23`|`>qil!LMGG{_Heq!BD>(Y-zV9wD)}hz25JA37YR%39;kI4y9pgtcUass6 zP24}ZY$vvYeI`zy&)A_X#nY3017ap*0&jx|mVwyGhg3;!keU53a}Uhm3BZI$N$6Se zLWlAmy1S0xKJm4G_U@sN_Tm=`$xWJSEwKU98rZ&)1R^*$$1vA3oG#&*%SMxY_~oGP zP&PFJatFLM-Ps%84IV-+Ow)T{C7cqUAvauy4C z(FRz&?6$Rypj{xO!`y=*J5o4@U8Q-(y5(*=YoKeZ+-1YdljXxkA#B)zo=FeQH#?Le zycNUmEEHWO9a=X^pb#&cOq7-`7UA87#|S22)<7RUtZo|(zibX=w;K3qur9vy#`MNV z6UUcf9ZwEnKCCp+OoBnF@OdbvH)ANXO0o~Pi9l8=x3))}L<#vO0-~O4!~--Ket?d} zJaqsj<@CD1%S2cTW%rOP{Vto%0sGW~1RMa_j^)5nil0Yw- z0EE#bP+l4#P^%PQ+N*oxu1Zq05xZ!bXfYTg>9c{(Iw*lnjR^>kz%lAN^zFce7rppy zY8zA~3GD=A6d*hze&l4D_wA~+O!56)BZTe_rEu}Ezi<4!kG|W#amBZ5{&XS2@6R~H z{9o^y*BkH4$~yX9U&@CgbOzX1bn9xqF|zh$Dh0Y5y*E0e90*$!ObrHY3Ok0`2=O~r zCuke6KrP9KOf?V(YDsM<6pX2nVoN%M$LT^q#FmtaF?1^27F*IcNX~XRB(|hCFvdcc zc)$=S-)acdk$g4?_>jRqxpI6M3vHZk?0c^3=byamYDNf;uB{3NlKW5IhnOS3DNkMV z?tK8?kJ}pmvp%&&eTVOVjHP`q34hN1@!aK}H(K!vI`~gf|Gv+FNEQD5Yd<~yX7k_l h&G-K)@HZb3BABY{)U1?^%I#E6`MGoTtustd{~yM6srvu` literal 0 HcmV?d00001 diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square150x150Logo.scale-200.png b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..af49fec1a5484db1d52a7f9b5ec90a27c7030186 GIT binary patch literal 2937 zcma)84OCO-8BSud5)jwMLRVKgX(S?$n?Ld|vrsm<$CF7)&zTbyy1FE5bU`Q17MRv`9ue$;R(@8kR;#vJ*IM0>cJIAOte!d7oRgdH zd%ySjdB6L9=gX^A6)VzH7p2l@v~3zJAMw|DFy#^)F@@F*`mqUn=Il>l)8_+ab;nOW{%+iPx z+s{Eu|&pIs)Z7{La9~?xKfyl z#43?gjEL15d4WbOZo#SiP%>DB^+BcnJ=7dHEe;r#G=tuw|ka z%q@}##Uh7;tc%L_64m(kHtw74ty%BJMb)_1)#S0j`)F8_1jF7vScpsnH=0V19bO8y zR`0SjIdCUo&=>JwMQF8KHA<{ODHTiQh}0^@5QRmCA?gOH6_H3K^-_sNB^RrdNuK-R zOO*vOrKCVvDwgUck`kF(E7j{I#iiN;b*ZdCt4m@HPA`EuEqGGf4%!K<;(=I=&Vyrw z%TwcWtxa}8mCZ%Cyf&ActJ6_$ox5z6-D!0-dvnRx6t7y3d+h6QYpKWO;8OdnvERo7 zuEf>ih5`wqY)~o@OeVt-wM?Q!>QzdGRj!bz6fzYrfw$hZfAKzr2-M+D+R>}~oT574c;_3zquHcElqKIsryILt3g8n3jcMb+j?i?-L3FpZJ z2WRVBRdDPc+G5aaYg#5hpE+6nQ|(VSoxT3|biF;BUq#==-27Xi=gihDPYP$7?=9cP zYKE$jeQ|3~_L0VG-(F~2ZPyD0=k{J4Q~h(t__{-mz_w8{JDY9{`1ouzz!Vr5!ECdE z6U~O1k8c}24V7~zzXWTV-Pe4)y}wQJS&q%H5`Fo_f_JvIU489aCX$;P`u#!I-=^4ijC2{&9!O&h>mi?9oYD=GC#%)6{GzN6nQYw+Fal50!#x^asjBBR50i`+mho*ttoqV)ubM2KD9S~k7+FR4>{29?6 z{!l6kDdyTN0YJ9LgkPWeXm|gyi@zM3?0@{&pXT12w|78&W-q!RRF)&iLCEZVH<|fR zN0fr2^t8H(>L?>K#>^+jWROLral(Qy-xoBq1U7A&DV||wClb)Otd9?(gZ|8znMF}D zf<1haWz^s0qgecz;RFGt0C-B4g`jNGHsFU+;{<%t65v^sjk^h$lmWn#B0#_)9ij&d z-~lc`A)YYExi^7sBuPM^Y|wA2g*5?`K?#7tzELQYNxGo$UB$4J8RJp1k(8Jj+~hMT zlN~>M@KTTh^--8y3PK_NZ@AC!{PT=CziBzGd+wTJ^@icH!Bd}%)g8V)%K?|c&WTUk zy}qv1C%(fjRoZ4ozC3{O%@5?)XzH35zHns$pgU*Q?fj4v?fp1Qbm+j;3l;9jam9Da zXVcKjPlQ73x78QPu|Ffm6x?`~e3oD=gl=4kYK?={kD5j~QCXU)`HSdduNNENzA*2$ zOm3PzF!lN5e*06-f1Uot67wY#{o-S1!KZ7E=!~7ynnk9_iJR#kFoNbAOT#^2Gd17F zMmvU6>lndZQGd|ax9kUoXXO+$N?|j@6qpsF&_j7YXvwo_C{JpmLw5&#e6k>atv%es z5)7r*Wvv_JkUpT}M!_o!nVlEk1Zbl=a*2hQ*<|%*K1Glj^FcF`6kTzGQ3lz~2tCc@ z&x|tj;aH&1&9HwcJBcT`;{?a+pnej;M1HO(6Z{#J!cZA04hnFl;NXA+&`=7bjW_^o zfC40u3LMG?NdPtwGl>Tq6u}*QG)}-y;)lu-_>ee3kibW(69n0$0Zy!}9rQz%*v1iO zT9_H>99yIrSPYVy6^);rR}7Yo=J_T@hi+qhTZXnVWyf;JDYm5#eYLTxr*?kiNn!+Y zQ+LUkBafNJ#rH#C(?d5^;gw9o#%daEI{mA*LHPIHPU`#|H$hD zwm>0&+kahQ)E#%~k>&5@&#Vg82H?s%71=)(soi@174pi9--2{w{1$}Sz4zGn3Du&x bht0Iza^2ykEt4(epJ78uh5nDlX8(TxzDYwP literal 0 HcmV?d00001 diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square44x44Logo.scale-200.png b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ce342a2ec8a61291ba76c54604aea7e9d20af11b GIT binary patch literal 1647 zcmaJ?eM}Q)7(e+G1Q(|`V9JhTI2>MkceK4;p;PR&$Pi?ejk3YQ_3o`S&|W_dsOZ8# zWPTt69g`t$ab`0cj-Y0yiBSOqmd)tG7G(}M5aP0_%&9TijB#&)I{zSE^4@#z^FF`l z`8{8`o%wlL(UI|y2!cdsuVamHH~H86F!*-15em4)NqUpCQM5?aoC_eCf@lV4wvF2a zjDQn1JBL69f&@2M3rvzJcfE!eZ8FZUBlFlC5RD)it33{mF9#B82AiyQE%w)`vlwa> zv{<1sm&kSKK$&%2jSFn7$t&P%%6Ue>R=EAnG8N7fqynWG8L3p!4801a;8{+nliO(qd(jNJ_?+9W3#hLIDLoT6~3fx9=`CC-D}-AMrpEO7HK zt3$GicGPc?GmDjy7K2P@La;eu4!$zWCZ`ym{Z$b zu-O6RM&K4JT|BIZB`E-gxqG%FzanI#+2FFmqHqXG7yxWB=w55RGOM)$xMb(>kSNR z2w=1AZi%z=AmG~yea~XaXJR!v7vLn(RUnELfiB1|6D84ICOS}^Zo2AdN}<&*h}G_u z{xZ!(%>tLT3J3<5XhWy-tg+6)0nmUUENLW8TWA{R6bgVd3X;anYFZ^IRis*_P-C-r z;i>%1^eL3UI2-{w8nuFFcs0e~7J{O2k^~Ce%+Ly4U?|=!0LH=t6()xi<^I-rs+9sF z*q{E-CxZbGPeu#a;XJwE;9S1?#R&uns>^0G3p`hEUF*v`M?@h%T%J%RChmD|EVydq zmHWh*_=S%emRC*mhxaVLzT@>Z2SX0u9v*DIJ@WC^kLVdlGV6LpK$KIrlJqc zpJ921)+3JJdTx|<`G&kXpKkjGJv=76R`yYIQ{#c-`%+`#V(7}Q;&@6U8!Td1`d;?N z_9mnI#?AA}4J!r)LN4!E-@H5eXauuB7TOawS>Y|{-P?NNx-lq+z1W-+y(;39P&&LP zL{N80?&=C*qKmdA^moMZRuPcD!B<*mq$ch=0Cnlitw#txRWhb3%TQvPqjkC`F69G4b! ze7z9MZ#+;_#l?H37UqUhDFb^l&s2{oM$3I0o^Q!yx;;V)QmCMo)Tb_ui|mit8MS?U zm##6$sZZ1$@|s%?l@>4Z<*Q}sRBSKMhb4I{e5LdEhsHIHTe8Bod5c>6QtT>$XgUBz z6MK`kO$=jmt@FqggOhJ5j~e@ygRbG;<{Vu)*+nn9aQeo0;$#j;|MS=S$&L?BeV25z xs3B`@=#`5TF{^6(A1rvdY@|-RtQ|iS5{tyX+wH?;n8E)G$kykv-D^wh{{!TZT%7;_ literal 0 HcmV?d00001 diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c02ce97e0a802b85f6021e822c89f8bf57d5cd GIT binary patch literal 1255 zcmaJ>TWs4@7*5+{G#S+&C!qC#> zf>5N3P6jO*Cz>ug*(_DmW=)kea&m$gZ^+nyiF`;j%w@}y8)>p*SH}C`m?DXeieF2U zyQHecc_L%Gh!7GMt+hG06y;+|p4>m~}PjA}rKViGiEnn7G0ZO<>G|7q;2?NwGCM3s?eued6%hd$B+ z*kQJ{#~$S=DFE(%=E+UkmlEI*%3llUf~8Ja9YU1Vui0IbGBkW_gHB%Rd&!!ioX zs40O?i9I{};kle7GMvE7(rk`la=gTI)47=>%?q@^iL-nUo3}h4S}N-KHn8t5mVP8w z&bSErwp+37 zNJJ8?a|{r5Q3R0Z5s-LB1WHOwYC@7pCHWND#cL1cZ?{kJ368_*(UDWUDyb<}0y@o# zfMF016iMWPCb6obAxT$JlB6(2DrlXDTB&!0`!m??4F(qWMhjVZo?JXQmz`1*58Z=& zcDmB|S-E@j?BoFGix0flckqdS4jsPNzhfWyWIM98GxcLs89C(~dw%$_t;JjX-SD}E zfiGV;{8Q%8r}w9x>EEigW81>`kvnU@pK)4+xk9@+bNj9L!AAZ@SZ@q|)&BmY3+HZx zul~BeG4|}-;L%cHViQGQX?^zFfO0&#cHwel=d`lH9sJ-@Sl@n*(8J2>%Ac`IxyY?Q z{=GhWvC#gu-~Ia7*n{=+;qM?Ul_wy1+u7ho;=`>EwP^g~R@{unBds`!#@}tluZQpS zm)M~nYEifJWJGx?_6DcTy>#uh%>!H9=hb^(v`=m3F1{L>db=<5_tm+_&knAQ2EU$s Mu9UqpbNZeC0BbUo^Z)<= literal 0 HcmV?d00001 diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/StoreLogo.png b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..7385b56c0e4d3c6b0efe3324aa1194157d837826 GIT binary patch literal 1451 zcmaJ>eN5D57_Z|bH;{0+1#mbl)eTU3{h)Wf7EZV?;HD@XL@{B`Ui%(2aMxQ~xdXSv z5nzWi(LW)U2=Vc-cY@s7nPt{i0hc6!7xN4NNHI#EQl>YNBy8l4%x9gr_W-j zEZMQmmTIy(>;lblRfh`dIyTgc9W5d!VP$L4(kKrN1c5G~(O_#xG zAJCNTstD^5SeXFB+&$h=ToJP2H>xr$iqPs-#O*;4(!Fjw25-!gEb*)mU}=)J;Iu>w zxK(5XoD0wrPSKQ~rbL^Cw6O_03*l*}i=ydbu7adJ6y;%@tjFeXIXT+ms30pmbOP%Q zX}S;+LBh8Tea~TSkHzvX6$rYb)+n&{kSbIqh|c7hmlxmwSiq5iVhU#iEQ<>a18|O^Sln-8t&+t`*{qBWo5M?wFM(JuimAOb5!K#D}XbslM@#1ZVz_;!9U zpfEpLAOz=0g@bd6Xj_ILi-x^!M}73h^o@}hM$1jflTs|Yuj9AL@A3<-?MV4!^4q`e z)fO@A;{9K^?W?DbnesnPr6kK>$zaKo&;FhFd(GYFCIU^T+OIMb%Tqo+P%oq(IdX7S zf6+HLO?7o0m+p>~Tp5UrXWh!UH!wZ5kv!E`_w)PTpI(#Iw{AS`gH4^b(bm^ZCq^FZ zY9DD7bH}rq9mg88+KgA$Zp!iWncuU2n1AuIa@=sWvUR-s`Qb{R*kk(SPU^`$6BXz8 zn#7yaFOIK%qGxyi`dYtm#&qqox0$h=pNi#u=M8zUG@bpiZ=3sT=1}Trr}39cC)H|v zbL?W)=&s4zrh)7>L(|cc%$1#!zfL?HjpeP%T+x_a+jZ16b^iKOHxFEX$7d|8${H-* zIrOJ5w&i$>*D>AKaIoYg`;{L@jM((Kt?$N$5OnuPqVvq**Nm}(f0wwOF%iX_Pba;V z;m@wxX&NcV3?<1+u?A{y_DIj7#m3Af1rCE)o`D&Y3}0%7E;iX1yMDiS)sh0wKi!36 zL!Wmq?P^Ku&rK~HJd97KkLTRl>ScGFYZNlYytWnhmuu|)L&ND8_PmkayQb{HOY640 bno1(wj@u8DCVuFR|31B*4ek@pZJqxCDDe1x literal 0 HcmV?d00001 diff --git a/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Wide310x150Logo.scale-200.png b/p09_Concurrency_Asynchrony/ex_050_010_Threading_en_UWP/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..288995b397fdbef1fb7e85afd71445d5de1952c5 GIT binary patch literal 3204 zcmbVPeQXow8NYmBd90>}0NP?GhXW~VaeThm=a0tV#EwJMI!)6M3}|c4_Bl3=Kd>G0 z(GHx1wl<7(tP?FsOQkTilSo*iIvF%uArExJ73~P zSv1xEy!U(Wd4A9D`FQV@W3@F^qJ@PEF$@z`Z!*BbFsS(^?B zyiAzJ+q})bkgiQHWqEb*jJD-coHYr1^iocg)l!Qa{Xqs-l~6J}p-|##ZHYofskQ3$ zI0;xzXyhazBeXhIsg5A=%ufo@f)1yy&ScKS0;HF^!r_2UE^lpZEom(+@duma3awTv zCrCL-%D_SvYWIcdHkmI}#50(fkUi)Qgx!80ju>g1za^}ff>JI8Z@^-iCiaCgg@TgF z+vtE?Q9{VQUX&MW9SYYmGcxA14%N2@7FwBTD4N<(2{nWgV8$e3?-F=L^&FrtWn~(U_Q~~^uYiyeY6-KoTnfh9AWz@ zIKje0)u!_Lw)E}G!#kEfwKVdNt(UAf9*f>tEL_(=xco-T%jTi@7YlC3hs2ik%Le0H ztj}RTeCF(5mwvi3_56>-yB?l;J>-1%!9~=fs|QcNG3J~a@JCu`4SB460s0ZO+##4fFUSGLcj_ja^fL4&BKALfb#$6$O?>P@qx2Agl^x0i&ugt zsy5Pyu=()`7HRMG3IB7F1@`_ z+-!J%#i6e^U$e#+C%Q>_qVRzWRsG^W_n+@OcX@vzI&z;mzHNb!GQ?LWA(wtpqHqTM z1OFw_{Zn?fD)p)`c`kOgv{de=v@suGRqY{N^U7gI1VF3*F=obwaXI6ob5__Yn zVTguS!%(NI09J8x#AO_aW!9W7k*UvB;IWDFC3srwftr{kHj%g)fvnAm;&h_dnl~

MY- zf+K}sCe8qU6Ujs`3ua{U0Of$R_gVQBuUA za0v=mu#vIOqiiAZOr&h*$WyOw&k-xr$;G4Ixa!#TJNr>95(h>l%)PUy4p+^SgR(uR zta%k*?ny-+nAr8spEk1fo{J4i!b^Fia`N{_F6@zidA2ZTTrjl#^5Z-2KfB@Cu}l9s z(*|Z2jc?p~vn2f)3y9i*7zJV1L{$?|&q)4oaT;uXi6>1GkRXVTOzAz(RHEmr=eFIi z`}<>-Q?K0GN8!IYxeP1XKXO+jsJbp~o^);Bc;%b7Flpe7;1`Ny@3r7ZR;?R)aJt8C ziNlEC<@3f_lIV4TwV}&e;D!Ee5_|e#g0LUh=5vmYWYm7&2h*M>QPKvGh9-)wfMMW3 z8J9b%1k7dzPzO0_NGQy92BZ^FR6R~6;^6?lqO;-QUP4BY%cG%3vEhbm#>4vIhPBh3 z-+pZGjh$x%Hp{?=FHsMp0&wNPlj00us{&`1ZOZTqs8%4X&xH=UDr*xyBW(Zp&Em94 zf)ZSfn#yg0N)>!1kWdkqJ^S*z0FF5|fj&qcE#Na|%OY0$uO>!&hP+1ywfD_WXk@4J(?MBftK7>$Nvqh@tDuarN%PrTLQ2Uzysx>UV=V zk^RrDSvdQ?0;=hY67EgII-f4`t=+i*yS=Y~!XlqIy_4x&%+OdfbKOFPXS2X5%4R{N z$SQMX^AK6(fA + + + + + + + + + + +