Partage
  • Partager sur Facebook
  • Partager sur Twitter

[DEBUTANT] Recuperer sélection d'une List C#

    20 septembre 2021 à 17:52:31

    Bonjour,


    Je débute et j'aimerais récupérer la réponse de l'utilisateur quand on lui soumet une List dans la console ? Par exemple:


    Je lui demande de faire un choix dans les différentes propositions soit:

    1 pour tete

    2 pour jambes

    3 pour ventre


    Je souhaite que lorsqu'il presse 1, 2 ou 3, je puisse lui soumettre une autre liste issue de la tête, jambes ou ventre par exemple pour la tête (donc réponse 1 dans le Cons.Read), lui afficher yeux, oreilles, bouche, etc

    Je ne sais pas si c'est assez clair mais j'aimerais vraiment savoir comment faire et j'ai du mal à expliquer cette problématique dans une recherche google.


    Cordialement


    EDIT: En gros, comment faire une liste d'une liste d'une liste (arborescence de plusieurs niveaux) et récupérer les réponses à chaque fois pour au final proposer un objet (POO) avec plusieurs caractéristiques ?
    • Partager sur Facebook
    • Partager sur Twitter
      20 septembre 2021 à 19:58:52

      C'est vraiment fonction de ce que vous faites avec après.

      Moi, bêtement, j'utilise le pattern prototype avec "Dictionary", typées si la profondeur est la même pour tous les chemins de choix.

      Un Dictionnaire qui à chaque clé associe un autre dictionnaire, jusqu'au dernier niveau où le dictionnaire contient des paires clé,valeur ou la clé est le dernier choix et la valeur un prototype de l'object à "créer/cloner".

      Mais si vous voulez plus de souplesse, créer votre arbre de décision à partir d'un fichier de configuration et pas en dur => Dictionnaire pas forcément très typé.

      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
        21 septembre 2021 à 0:15:17

        Bonjour,

        J'ai fait une petite recherche sur Google et j'ai trouvé les IF/Switch

        J'ai pensé utiliser des dictionnaires dans des dictionnaires mais dès le second niveau je dois pouvoir proposer plusieurs propositions et différentes pour chaque choix évidemment mais néanmoins immuables.. Je ne sais pas si les clés des dico peuvent répertorier d'autres List de list

        Avec la solution du switch, devrais-je faire:

        int reponse = Console. ReadLine();
        if (reponse = "nombre de reponse dispo dans la categorie")
        {
        case 1: Console.WriteLine( ListDeListe2());
        break;

        case 2: Console.WriteLine( ListDeListe3());
        break;

        etc..

        }

        int reponseSuiv = Console. ReadLine();
        if (reponseSuiv = "nombre de reponse dispo dans la categorie")
        {
        case 1: Console.WriteLine( ListDeListeSuiv());
        break;

        case 2: Console.WriteLine( ListDeListeSuiv());
        break;

        etc..

        }

        Si oui, comment finir sir l'affichage de différents objets crées (type poo) ?

        Si non, je veux bien une autre solution si vous en avez une.



        Merci d'avance pour le temps accordé

        • Partager sur Facebook
        • Partager sur Twitter
          21 septembre 2021 à 12:25:06

          Oulà, vous en êtes à savoir distinguer des "if" et des "switch/case" ?

          On va laisser de côté les trucs à base de Design Pattern Prototype et autres astuces qui évitent de tout mettre en dur.

          Ne mélangez pas trop les "if" et les "switch/case".

          Les "switch/case", c'est une syntaxe qui permet de factoriser/simplifier tout un tas de "if".

          Vous pouvez donc remplacer un ensemble de "switch/case" par une ribambelle de "if/else" qui se suivraient les uns les autres.

          Donc commencez par un truc un peu "dégueux", type :

          object res = null;
          
          AfficherMenu(listeRacine);
          
          string response = Console.ReadLine();
          
          switch(response)
          {
              case "1" :
                  {
                      AfficherMenu(listeTete);
                      response = Console.ReadLine();
          
                      switch(response)
                      {
                          case "1" :
                              res = new Yeux();
                              break;
                          case "2" :
                              res = new Oreilles();
                              break;
                          case "3" :
                              res = new Bouche();
                              break;
                          default :
                              {
          ....
                              }
                              break;
                      }
                  }
                  break;
              case "2" :
                  {
          ....
                  }
                  break;
              case "3" :
                  {
          ....
                  }
                  break;
              default :
                  {
          ....
                  }
                  break;
          }



          Mais je pense que vous mettez la charrue avant les bœufs.

          EDIT :

          Une version qui utilise de Design Pattern Prototype et une arborescence "dynamique" (ADVANCED!):

          (La région "#region Init" devrait être avantageusement remplacé par un mécanisme de chargement depuis fichier de configuration)

          class Yeux : ICloneable
          {
              public object Clone()
              {
                  return MemberwiseClone();
              }
          
              public override string ToString()
              {
                  return "Yeux";
              }
          }
          
          private static void DisplayMenu(Dictionary<int, object> dic)
          {
              foreach (var item in dic.Keys)
              {
                  string name = "";
                  if(dic[item] is Tuple< string, Dictionary<int, object>>)
                  {
                      name = ((Tuple<string, Dictionary<int, object>>)dic[item]).Item1;
                  }
                  else if (dic[item] is Tuple<string, object>)
                  {
                      name = ((Tuple<string, object>)dic[item]).Item1;
                  }
                  else if (dic[item]!=null)
                  {
                      name = dic[item].ToString();
                  }
                  Console.WriteLine(item + (String.IsNullOrEmpty(name) ?  "" : " - " + name));
              }
          }
          
          private static object ChooseElement(Dictionary<int, object> dic)
          {
              object ret = null;
              bool rep_ok = false;
              int rep_int;
          
              do
              {
                  DisplayMenu(dic);
                  string rep = Console.ReadLine();
                  rep_ok = int.TryParse(rep, out rep_int);
                  if (rep_ok && !dic.ContainsKey(rep_int))
                  {
                      rep_ok = false;
                  }
              } while (!rep_ok);
          
              if (dic[rep_int] is Tuple<string,Dictionary<int, object>>)
              {
                  ret = ChooseElement(((Tuple < string, Dictionary<int, object>>)dic[rep_int]).Item2);
              }
              else
              {
                  ret = dic[rep_int];
              }
              return ret;
          }
          
          static void Main(string[] args)
          {
              #region Init
              Dictionary<int, object> root = new Dictionary<int, object>();
          
              Tuple <string,Dictionary<int, object>> tete = new Tuple<string, Dictionary<int, object>>("tête", 
                  new Dictionary<int, object> {
                      {1, new Tuple<string, object>("yeux", new Yeux()) },
                      {2, new Tuple<string, object>("oreilles", new object()) },
                      {3, new Tuple<string, object>("bouche", new object()) },
                  });
          
              Tuple < string,Dictionary<int, object>> jambe = new Tuple<string, Dictionary<int, object>>("jambe",null);
          
              Tuple < string,Dictionary<int, object>> ventre = new Tuple<string, Dictionary<int, object>>("ventre", null);
          
              root[1] = tete;
          
              root[2] = jambe;
          
              root[3] = ventre;
          
              #endregion
          
              object res = ChooseElement(root);
          
              object myObj = res;
              if (res is ICloneable)
              {
                  myObj = ((ICloneable)res).Clone();
              }
          
          ....
          
          }


          Il y a aura peut-être 2-3 trucs à modifier pour prendre en compte des profondeurs d'arbres plus importants, c'est un peu inconvénient d'un typage "faible". (Avec quelques classes en plus, on peut revenir à un typage fort)

          myObj contient, in fine, soit l'objet choisi, soit un clone de celui-ci.

          -
          Edité par bacelar 21 septembre 2021 à 13:44:54

          • Partager sur Facebook
          • Partager sur Twitter
          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
            22 septembre 2021 à 1:45:27

            Wow merci pour la réponse ultra complète, elle m'aidera dans l'avancement de mon projet sur le long terme pour l'evolution du code.

            Pour ce que j'ai posté, j'ai tapé un peu vite en plus de ne jamais me relire..

            Voilà ce que j'ai donc fait pour l'instant et qui marche (switch est dans une fonction : AfficherListeSuiv())

            Je vais néanmoins étudier votre code afin de voir pourquoi votre syntaxe est plus efficiente ! Pour votre deuxième image je n'y comprends rien mais c'est le temps que je bash un peu tout ça afin que ce soit plus clair pour moi.

            Est il possible de laisser se sujet ouvert au cas ou j'aurai des questions supplémentaires quant à l'évolution du programme ?

            Merci encore

            Bien à vous

            -
            Edité par LoicG1 22 septembre 2021 à 1:46:34

            • Partager sur Facebook
            • Partager sur Twitter
              22 septembre 2021 à 10:09:44

              Pour du code, postez le avec le bouton [</>] plutôt que des copies d'écran.

              Mon 2ème code est là pour montrer comment on peut rendre les choses très flexible (changement d'arborescence, de langue, etc.) sans avoir à modifier le code. Mais si c'est du code "jetable" pas la peine de sortir l'artillerie lours.

              Mais dans un forum, on a tendance à donner la manière "grosse Berta" car les PO ont normalement une base minimale pour faire du code "jetable".

              Pensez à utiliser des verbes "d'action" dans le nom de vos fonctions. C'est bête, mais cela évite d'en faire des fonctions fourre-tout.

              "ZonesTete", elle fait quoi ? Elle affiche les choix possibles ? Elle crée le type d'objet choisi ? etc...

              En découpant votre code et en supprimant les partie de code en doublon en le factorisant (DRY, Dont Repeat Yourself), il devient "naturellement" plus flexible.

              Par exemple, dans mon 2ème code, la partie "Affichage" des choix est générique et séparé du reste, cela permet d'implémenter très simplement une vérification des entrés de l'utilisateur : la porte d'entrée principale des problèmes pour un programme.

              • Partager sur Facebook
              • Partager sur Twitter
              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                23 septembre 2021 à 0:37:18

                Oui, j'aurais du la nommer AfficherZoneTete (qui affiche la liste des différentes parties de la tête avec la possibilité d'en choisir une en particulier pour aller plus loin dans les "yeux" par exemple, soit: pupille, cornée, etc). Je crée la liste, et l'appelle donc en fonction du choix du client. J'aimerais au final afficher une classe d'objet qui contient différentes infos donc en utilisant le constructeur et cie. Il n'y a aucune utilité à ce programme, c'est juste histoire de travailler ce que j'ai acquis et de travailler ma logique, la refactorisation et les déclinaisons en site web/appli android via API Rest.

                Je me suis renseigné sur le Prototype Design Pattern et ça à l'air extrêmement utile en effet et plutôt compréhensible quand on a compris mais c'est bizarre que je n'ai pas eu de chapitre là dessus.. J'aimerais vraiment maitriser le C# dans sa globalité ! Pour cela, je compte embrayer sur cette formation: https://www.udemy.com/course/apprendre-csharp-et-le-developpement-de-logiciels-avec-wpf-net-core/

                Il y a le contenu détaillé un peu plus bas. Si vous pouviez me dire si ça vous semble complet. J'enchainerai avec des ressources anglophones par la suite et surement des livres pour aiguiser ma maitrise. Ayant une grosse xp en HTML/CSS, est-ce que le C# est considéré comme un langage back-end ? Je pense que oui mais je n'ai vu aucun Dev Full Stack travaillé avec. C'est juste une question comme ça car je programme pour mon plaisir perso et j'ai déjà une activité qui n'a rien à voir et je ne souhaite pas changer ou me reconvertir.

                • Partager sur Facebook
                • Partager sur Twitter
                  23 septembre 2021 à 12:15:14

                  >Oui, j'aurais du la nommer AfficherZoneTete ...avec la possibilité d'en choisir une en particulier pour aller plus

                  Erreur, une chose importante, négligée généralement dans les cours, c'est de bien nommer ces variables/méthodes/classes.

                  Ici, votre "AfficherZoneTete" ne fait pas QUE ce qu'elle indique avec son nom (contraire au 'S' des principe SOLID de la POO).

                  "SelectionnerZoneTete" serait plus pertinent, quit à avoir aussi une méthode "AfficherZoneTete" juste pour afficher les choix.

                  Dans mon 2ème code, j'ai une méthode "DisplayMenu" qui est générique et donc utilisable dans n'importe quelle méthode de "Selection". (Application du principe DRY).

                  Tout ceci n'est pas lié à C# mais bien plus à la conception (objet ou pas).

                  >et les déclinaisons en site web/appli android via API Rest.

                  Attention, l'aspect asynchrone de ce type de dialogue impose des choses/techniques et l'approche "tout en dur" n'est clairement pas fait pour.

                  Les choix liés aux contraintes, c'est la fonction même de l'Analyse (de la problématique), donc toujours pas lié à un langage particulier.

                  >mais c'est bizarre que je n'ai pas eu de chapitre là dessus

                  "Chapitre" de quoi ? Un cours sur les Design Pattern, oui ça serait bizarre, mais pour un cours sur le C#, non, c'est pas son rôle. Vous n'avez pas besoin de connaitre tous les Design Pattern pour comprendre le C#. Mais vous devez connaitre un minimum de Design Pattern pour créer une solution "souple" à un problème donné.

                  >J'aimerais vraiment maitriser le C# dans sa globalité !

                  Moi, je le maîtrise pas dans "sa globalité" mais cela ne m'empêche pas d'essayer d'appliquer correctement les principes de l'analyse, de la conception, de la POO, etc...

                  Pour la formation Udemy, on ne devient pas programmeur "efficace" juste en regardant quelqu'un faire, il y a des choses bizarre comme du Winform dans un cours sur WPF, mais il semble reprendre depuis les bases, donc pas forcement pertinent pour tout le monde, mais bien plus "vendeur".

                  Ne cherchez pas la "complétude" (Gödel es-tu là), il faut juste que cela donne les bases pour pouvoir chercher et évoluer (oui même quand un langage n'évolue pas, ce qui n'est pas le cas du C#, la manière de s'en servir efficacement change).

                  >est-ce que le C# est considéré comme un langage back-end ?

                  Dénomination complètement marketing et "artificielle", qui, de mon point de vue, ne sert qu'à mettre des personnes dans des cases pour que les commerciaux puissent les mettre dans les paquets de lessive avec une étiquette de prix dessus.

                  La simple création de Node.js a fait passer le "JavaScript" de langage d'IHM à un langage "full stack" (dénomination de marketeux, on est d'accord).

                  En fonction des framework utilisés, C# peut faire de back, du middle, du front, quand la conception n'est pas un énorme maelström de code spaghetti.

                  Mais, bon, avec l’échec des technologies comme SilverLight ou des Navigateurs Edge, ne se baser que sur C# pour faire une IHM Web, c'est plutôt "couillu".

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                  [DEBUTANT] Recuperer sélection d'une List C#

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  • Editeur
                  • Markdown