Type par énumération
🎯 Objectifs
- Définir une énumération
enum - Définir la condition
switch/case - Définier l'initilisateur d'objet et collection
✅ L'énumération enum
📜 Définition
Une énumération est un type de valeur spécial que l'on appel enum. Elle permet de définir une suite
de constantes d'entier nommées.
🔢Valeurs par défaut
Les noms définis sont liés à une valeur numérique entière et elle commence à 0 par défaut:
public enum ChoixAlignement
{
Gauche, // commence à zéro
Droit, // 1
Centre // 2
}
#️⃣ Valeur de départ spécifiée
Il est possible de spécifier la valeur de départ qui va augmenter de 1 par la suite:
public enum ChoixAlignement
{
Gauche = -1,
Droit, // 0
Centre // 1
}
*️⃣ Valeurs toutes spécifiées
Il est aussi possible de spécifier toutes les valeurs:
public enum ChoixAlignement
{
Gauche = 2,
Droit = 4,
Centre = 6
}
✅ La condition switch
📜 Définition
La structure de contrôle de sélection switch est une condition C# qui permet de facilement
illustré plusieurs conditions d'évaluation sur une valeur. Cette structure offre beaucoup de lisibilité
aux développeurs contrairement une une longue liste de conditions if-else.
int choix = cboChoix.SelectedIndex;
switch (choix)
{
case 0:
txtVotreChoix.Text = "Alignement à gauche";
break;
case 1 :
txtVotreChoix.Text = "Alignement à droite";
break;
case 2 :
txtVotreChoix.Text = "Alignement au centre";
break;
}
🛠️ Énumérations et la structure switch-case
Cette structure fait un excellent duo avec les énumérations:
ChoixAlignement choix = (ChoixAlignement)cboChoix.SelectedIndex;
switch (choix)
{
case ChoixAlignement.Gauche:
txtVotreChoix.Text = "Alignement à gauche";
break;
case ChoixAlignement.Droit:
txtVotreChoix.Text = "Alignement à droite";
break;
case ChoixAlignement.Centre:
txtVotreChoix.Text = "Alignement au centre";
break;
}
✅ Initialiseur d'objet et de collection
📜Définition
Pour sauver du temps, c# nous permet d'initialiser des objets directement lors de leurs créations. Il est donc possible de garder ce qui est strictement nécessaire d'initialisation dans le constructeur et de quand-même rapidement créer un objet complet.
💡 Exemples
Voici un exemple d'initialisation d'un objet avec un constructeur vide":
// Quelques fois on ne dispose pas d'un constructeur avec plusieurs paramètres.
// Mais il est tout de même possible de fournir des valeurs aux propriétés
// au moment de l'instanciation, en utilisant un initialiseur d'objet comme suit :
m_objMontre = new Montre() { Heures = 12, Minutes = 20, Secondes = 55 }
Il est aussi possible d'effectuer cette initialisation avec des collections d'objet tel que la liste:
m_colPersonnes = new List<Personne>() {
new Personne() { Nom = "Robert Lapointe", Nas = "276187261" },
new Personne() { Nom = "Louise Tremblay", Nas = "527189354" },
new Personne() { Nom = "Denis Verreau", Nas = "782356273"}
};
✅ Exemples d'utilisation
Explorons quelques exemples d'utilisations de ce que nous avons appris aujourd'hui:
🎭 Exposer différents paramètres de configuration
Les énumérations et les switch-case sont très pratique lorsqu'on veut exposer
des options. Avec IntelliSense, les enum peuvent exposer très clairement
des fonctionnalités sans pour autant s'enchaîner avec la gestions de string ou
de chiffres magiques.
L'appel d'une méthode générant un fichier du format pdf pourrait se faire comme suit:
string rapportHTML = GenererRapport(FormatRapport.Pdf);
...et voici comme l'on pourrait implémenter la fonction en considérant le choix du format passé en paramètre:
public enum FormatRapport { Pdf, Html, Markdown }
public string GenererRapport(FormatRapport format)
{
string rapport = "";
switch(format)
{
case FormatRapport.Pdf:
rapport = GenererPDF();
break;
case FormatRapport.Html:
rapport = GenererHTML();
break;
case FormatRapport.Markdown:
rapport = GenererMarkdown();
break;
}
return rapport;
}
🧑⚖️ Permissions, filtres et comportements
Il est possible de combiner des valeurs d'une énumération pour spécifier des choix multiples. Il faut s'assurer de faire des bons de deux après la première valeur.
Voici un exemple d'options que vous risquez de souvent rencontrer lorsque vous utiliser la bibliothèque de Microsoft. Notez
l'utilisation de l'opérateur logique | pour combiner les valeurs.
Rechercher("csharp", OptionsRecherche.IgnorerCasse | OptionsRecherche.MotEntier);
...et voici comment on pourrait implémenter la vérification des options choisies avec l'opérateur logique &.
public enum OptionsRecherche
{
Aucune = 1,
IgnorerCasse = 2,
IgnorerAccents = 4,
MotEntier = 8
}
public void Rechercher(string texte, OptionsRecherche options)
{
bool ignorerCasse = (options & OptionsRecherche.IgnorerCasse) != 0;
bool ignorerAccents = (options & OptionsRecherche.IgnorerAccents) != 0;
bool MotEntier = (options & OptionsRecherche.MotEntier) != 0;
// …
}
Si c’est un Flags, utiliser des puissances de 2 tel que 1,2,4,8,16… sinon les combinaisons deviennent incohérentes.
🪄 Éviter les chiffres magiques
Si vous remarquez que votre application contient beaucoup de chiffre magique, tentez de les remplacer par des constantes et/ou des énumérations. L'intention derrière vos chiffres magiques devient explicite et robuste.
public enum NiveauLog { Trace, Debug, Info, Warning, Error, Critical }
public void Log(NiveauLog niveau, string message) { /* … */ }
⚠️ Toujours prévoir un cas par défaut défensif.
Notez ici l'implémentation de rôles d'utilisateur:
public enum RoleUtilisateur { Etudiant, Enseignant, Admin }
Prenez garde de toujours prévoir un cas par défaut défensif. Bien qu'il n'y ait que trois rôles possibles dans l'énumération, rien n'empêche
un programmeur de transformer un int en votre enum et tout briser.
Le rôle 999 n'existe pas et peut-être qu'il pourrait venir briser votre code:
RoleUtilisateur roleDouteux = (RoleUtilisateur)999;
❌ Les enums et les tableaux
Il serait tenant de combiner les tableaux et les énumérations pour nommer nos indices de tableaux, mais ceci est une mauvaise pratique!
public enum NomColonne { Nom, Prenom, Solde }
string ligne = "Martel;Philippe;-45$";
string[] colonnes = ligne.Split(";");
// ❌ Mauvaise pratique et très dangereux.
Console.WriteLine($"{colonnes[(int)NomColonne.Prenom]} possède {colonnes[(int)NomColonne.Solde]} dollars.")
✅ Utilisez plutôt un dictionnaire
Un dictionnaire est une collection d'objet. Cette collection est similaire à une liste List<>, mais elle a la particularité de lier une donnée à un identifiant de façon très sécuritaire.
public enum NomColonne { Nom, Prenom, Solde }
Dictionary<NomColonne, string> colonnes = new Dictionary<NomColonne, string>()
{
{ NomColonne.Nom, "Martel" },
{ NomColonne.Prenom, "Philippe" },
{ NomColonne.Sold, "-45$" }
};
// ✅ Bonne pratique !
Console.WriteLine($"{colonnes[NomColonne.Prenom]} possède {colonnes[NomColonne.Solde]} dollars.")
📚 Ressources supplémentaires
👉 Notions C# : Instanciation objet
Vous devez réaliser le labo suivant : 🧪 Labo 3.1