1. #1
    Candidat au Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    décembre 2016
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : décembre 2016
    Messages : 2
    Points : 2
    Points
    2

    Par défaut Définition de classes et leur utilisation avec des List

    Bonjour à tous.

    Je suis en train d'apprendre le c# en autodidacte, je me suis fixé pour but d'arriver à écrire une application dans le genre du "snake" (le jeu).
    Je viens du delphi, je ne suis pas débutant en programmation, mais j'ai parfois du mal à mettre en code c# ce que je faisais en delphi, je bute sur des choses simples et je perds beaucoup de temps
    Et faire un copier-coller des nombreux codes du genre présents sur le net n'est pas très formateur ...

    Bref voila pour la courte présentation.

    Pour mon projet, j'ai défini 2 classes :
    - une qui contient la définition d'une coordonnée
    - une qui contient la définition du corps du serpent, en utilisant la classe coordonnée

    Ca nous donne donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    namespace Snake
    {
        class Coordonnee
        {
            public int X;
            public int Y;
        }
    }
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    namespace Snake
    {
        class Serpent
        {
            public List<Coordonnee> CorpsSerpent = new List<Coordonnee>();
        }
    }
    Ensuite arrive le moment où je veux utiliser ces classes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    namespace Snake
    {
        public partial class Form1 : Form
        {
            Serpent UnSerpent = new Serpent(); // Création du serpent
            Coordonnee UneCoordonnee = new Coordonnee(); // Création d'une coordonnée
     
            public Form1()
            {
                InitializeComponent();
                CreerNouveauJeu(); // Initialisation d'un nouveau jeu
            }
            ...
            private void CreerNouveauJeu()
            {
                UnSerpent.CorpsSerpent.Clear(); // Nettoyage du corps du serpent
     
                UneCoordonnee.X = 16; // Initialisation coordonnée X
                UneCoordonnee.Y = 1; // Initialisation coordonnée Y
                UnSerpent.CorpsSerpent.Add(UneCoordonnee); // Ajout de ces coordonnées au corps du serpent
     
                UneCoordonnee.X = 1; // Initialisation coordonnée X
                UneCoordonnee.Y = 1; // Initialisation coordonnée Y
                UnSerpent.CorpsSerpent.Add(UneCoordonnee); // Ajout de ces coordonnées au corps du serpent
            }
        }
    }
    Les deux éléments de la liste sont bien crées, mais ils ne sont pas initialisés correctement.
    Le deuxième ajout de coordonnées semble écrasé les valeur du premier, le couple de valeur (x,y)=(16,1) disparait de la liste.

    C'est peut être une incompréhension sur le fonctionnement des List, ou une partie du code mal placé (j'ai du mal avec ça aussi), ou autre chose ...
    J'ai besoin d'aide.

  2. #2
    Membre éprouvé
    Avatar de PixelJuice
    Homme Profil pro
    Ingénieur .NET & Game Designer
    Inscrit en
    janvier 2014
    Messages
    363
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur .NET & Game Designer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : janvier 2014
    Messages : 363
    Points : 1 220
    Points
    1 220

    Par défaut

    Bonjour,

    ton problème vient de ce bout de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
            private void CreerNouveauJeu()
            {
                UnSerpent.CorpsSerpent.Clear(); // Nettoyage du corps du serpent
     
                UneCoordonnee.X = 16; // Initialisation coordonnée X
                UneCoordonnee.Y = 1; // Initialisation coordonnée Y
                UnSerpent.CorpsSerpent.Add(UneCoordonnee); // Ajout de ces coordonnées au corps du serpent
     
                UneCoordonnee.X = 1; // Initialisation coordonnée X
                UneCoordonnee.Y = 1; // Initialisation coordonnée Y
                UnSerpent.CorpsSerpent.Add(UneCoordonnee); // Ajout de ces coordonnées au corps du serpent
            }
    Tu as défini Coordonnee comme une classe, et tu rajoutes toujours le même objet de cette classe. Du coup, si tu modifies les propriétés de cet objet, tout changera, car ta liste pour l'instant n'est rempli que du même et seul objet.

    Pour y remédier, soit tu créer un nouvel objet de type Coordonnee pour autant de coordonnées. Soit tu passes Coordonee en structure. C'est selon tes besoins.

    Si tu as des difficultés sur ce point, je te conseille de chercher la différence entre passage de valeur et passage de réference.
    Keep calm and debug it

    www.pixel-juice.net

  3. #3
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 054
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 054
    Points : 5 006
    Points
    5 006
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par PixelJuice Voir le message
    Tu as défini Coordonnee comme une classe, et tu rajoutes toujours le même objet de cette classe. Du coup, si tu modifies les propriétés de cet objet, tout changera, car ta liste pour l'instant n'est rempli que du même et seul objet.

    Pour y remédier, soit tu créer un nouvel objet de type Coordonnee pour autant de coordonnées. Soit tu passes Coordonee en structure. C'est selon tes besoins.
    Je dirais même que plutôt de passer par une (ou plusieurs) instance locale, il me semble préférable d'utiliser directement l'élément dans la liste.

    1/ En créant un constructeur adéquat à la classe "Coordonnee" :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    namespace Snake
    {
        class Coordonnee
        {
            public int X { get; private set; }
            public int Y { get; private set; }
     
            public Coordonnee(int x, int y)
            {
                 X = x;
                 Y = y;
            }
        }
        ...
        public partial class Form1 : Form
        {
            private void CreerNouveauJeu()
            {
                UnSerpent.CorpsSerpent.Clear(); // Nettoyage du corps du serpent
     
                UnSerpent.CorpsSerpent.Add(new UneCoordonnee(16, 1)); // Ajout de ces coordonnées au corps du serpent
                UnSerpent.CorpsSerpent.Add(new UneCoordonnee(1, 1)); // Ajout de ces coordonnées au corps du serpent
            }
        }
    }

    2/ En utilisant un constructeur dynamique (plus moderne, mais moins lisible, je trouve)
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    namespace Snake
    {
        class Coordonnee
        {
            public int X { get; private set; }
            public int Y { get; private set; }
        }
        ...
        public partial class Form1 : Form
        {
            private void CreerNouveauJeu()
            {
                UnSerpent.CorpsSerpent.Clear(); // Nettoyage du corps du serpent
     
                UnSerpent.CorpsSerpent.Add(new UneCoordonnee() { X = 16, Y = 1 }); // Ajout de ces coordonnées au corps du serpent
                UnSerpent.CorpsSerpent.Add(new UneCoordonnee() { X = 1, Y = 1 }); // Ajout de ces coordonnées au corps du serpent
            }
        }
    }

    2 bis/ En utilisant un constructeur dynamique (plus moderne, mais moins lisible, je trouve)
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    namespace Snake
    {
        class Coordonnee
        {
            public int X { get; private set; }
            public int Y { get; private set; }
        }
        ...
        public partial class Form1 : Form
        {
            private void CreerNouveauJeu()
            {
                UnSerpent.CorpsSerpent.Clear(); // Nettoyage du corps du serpent
     
                UnSerpent.CorpsSerpent.AddRange(new Coordonnee[] { new Coordonnee() { X = 16, Y = 1 }, new Coordonnee() { X = 1, Y = 1 } }); // Ajout de ces coordonnées au corps du serpent
            }
        }
    }

    3/ En modifiant directement les propriétés des instances dans la liste (mais ça peut vite être le bordel) :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    namespace Snake
    {
        class Coordonnee
        {
            public int X { get; set; }
            public int Y { get; set; }
        }
        ...
        public partial class Form1 : Form
        {
            private void CreerNouveauJeu()
            {
                UnSerpent.CorpsSerpent.Clear(); // Nettoyage du corps du serpent
     
                UnSerpent.CorpsSerpent.Add(new UneCoordonnee()); // Ajout de ces coordonnées au corps du serpent
                UnSerpent.CorpsSerpent.Add(new UneCoordonnee()); // Ajout de ces coordonnées au corps du serpent
                UnSerpent.CorpsSerpent[0].X = 16;
                UnSerpent.CorpsSerpent[0].Y = 1;
                UnSerpent.CorpsSerpent[1].X = 1;
                UnSerpent.CorpsSerpent[1].Y = 1;
            }
        }
    }
    On ne jouit bien que de ce qu’on partage.

  4. #4
    Candidat au Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    décembre 2016
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : décembre 2016
    Messages : 2
    Points : 2
    Points
    2

    Par défaut

    Merci de vos réponses

    @ StringBuilder
    J'ai utilisé la solution 2, ça marche effectivement bien mieux comme ça

    @ PixelJuice
    J'ai encore un peu de mal avec cette notion d'objet, je vais me renseigner sur les passages de valeur et références

    J'ai bien avancé du coup !

  5. #5
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    avril 2007
    Messages
    12 846
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : avril 2007
    Messages : 12 846
    Points : 23 139
    Points
    23 139

    Par défaut

    l'objet c'est la base oui
    en fait quand tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var c = new Coordonnee();
    new Coordonnee est exécuté en premier, ca créé un espace mémoire pour recevoir l'instance de cette classe (qui contient x et y, qui étant des int font 4 octets)
    puis l'adresse mémoire de cette instance est placée dans c
    si tu fais ensuite
    alors un nouvel espace mémoire est créé, et c pointe maintenant vers cette instance mémoire

    l'ancienne instance mémoire n'est ici plus pointée par personne, elle sera supprimée de la mémoire (mais ce n'est pas le sujet ici ^^)

    si tu fais
    d est un pointeur, qui va pointer vers la même instance que c ; ce n'est pas l'objet qui est dupliqué mais la référence vers celui ci
    donc modifier d.x "modifie" indirectement c.x
    il n'y a pas réellement de modification de c, c'est que vu que c'est la même instance ca va lire le même espace mémoire, donc ca reflète le changement
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : juin 2007
    Messages : 382
    Points : 584
    Points
    584

    Par défaut

    Citation Envoyé par StringBuilder Voir le message
    2/ En utilisant un constructeur dynamique (plus moderne, mais moins lisible, je trouve)
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    namespace Snake
    {
        class Coordonnee
        {
            public int X { get; private set; }
            public int Y { get; private set; }
        }
        ...
        public partial class Form1 : Form
        {
            private void CreerNouveauJeu()
            {
                UnSerpent.CorpsSerpent.Clear(); // Nettoyage du corps du serpent
     
                UnSerpent.CorpsSerpent.Add(new UneCoordonnee() { X = 16, Y = 1 }); // Ajout de ces coordonnées au corps du serpent
                UnSerpent.CorpsSerpent.Add(new UneCoordonnee() { X = 1, Y = 1 }); // Ajout de ces coordonnées au corps du serpent
            }
        }
    }
    À partir de quelle version du langage c'est possible avec des setters en private ?

  7. #7
    Max
    Max est déconnecté
    Expert éminent sénior
    Avatar de Max
    Homme Profil pro
    Artisan développeur
    Inscrit en
    mai 2007
    Messages
    2 848
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Artisan développeur
    Secteur : Industrie

    Informations forums :
    Inscription : mai 2007
    Messages : 2 848
    Points : 15 018
    Points
    15 018

    Par défaut

    Citation Envoyé par Noxen Voir le message
    À partir de quelle version du langage c'est possible avec des setters en private ?
    C# 2 il me semble

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : juin 2007
    Messages : 382
    Points : 584
    Points
    584

    Par défaut

    Citation Envoyé par Max Voir le message
    C# 2 il me semble
    Cette syntaxe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var c = new UneCoordonnee() { X = 16, Y = 1 }
    existe depuis C# 3 pour être plus précis, mais elle implique des setters publics puisqu'elle est équivalente à celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var c = new UneCoordonnee();
    c.X = 16;
    c.Y = 1;
    C'est toujours comme ça en C# 6. Je me disais qu'une version ultérieure pourrait éventuellement devenir plus permissive sur l'accessibilité du setter dans son usage au sein d'un initialiseur, néanmoins ce serait quand-même une atteinte au principe d'encapsulation.

  9. #9
    Max
    Max est déconnecté
    Expert éminent sénior
    Avatar de Max
    Homme Profil pro
    Artisan développeur
    Inscrit en
    mai 2007
    Messages
    2 848
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Artisan développeur
    Secteur : Industrie

    Informations forums :
    Inscription : mai 2007
    Messages : 2 848
    Points : 15 018
    Points
    15 018

    Par défaut

    Citation Envoyé par Noxen Voir le message
    Cette syntaxe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var c = new UneCoordonnee() { X = 16, Y = 1 }
    existe depuis C# 3 pour être plus précis, mais elle implique des setters publics puisqu'elle est équivalente à celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var c = new UneCoordonnee();
    c.X = 16;
    c.Y = 1;
    C'est toujours comme ça en C# 6. Je me disais qu'une version ultérieure pourrait éventuellement devenir plus permissive sur l'accessibilité du setter dans son usage au sein d'un initialiseur, néanmoins ce serait quand-même une atteinte au principe d'encapsulation.
    Oula j'ai mal compris ta question et donc ai répondu à côté de la plaque

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : juin 2007
    Messages : 382
    Points : 584
    Points
    584

    Par défaut

    Citation Envoyé par Max Voir le message
    Oula j'ai mal compris ta question et donc ai répondu à côté de la plaque
    C'est ce que j'avais déduit, j'ai donc précisé ma pensée :-)

  11. #11
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 054
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 054
    Points : 5 006
    Points
    5 006
    Billets dans le blog
    1

    Par défaut

    Oups, désolé, tapé mon code trop vite
    On ne jouit bien que de ce qu’on partage.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Classes PyQt et doublons avec des modules Python
    Par Neitsa dans le forum PyQt
    Réponses: 4
    Dernier message: 20/09/2011, 13h24
  2. Sprite manager : utilisation avec des classes derivées de Sprite
    Par TheDrev dans le forum Développement 2D, 3D et Jeux
    Réponses: 10
    Dernier message: 14/05/2008, 22h53
  3. Réponses: 2
    Dernier message: 14/12/2007, 02h47
  4. Utilisation avec des cartes d'acquisition
    Par engineer_23 dans le forum OpenCV
    Réponses: 0
    Dernier message: 26/07/2007, 13h17
  5. [JpGraph] Utilisation avec des sessions
    Par dervish dans le forum JpGraph
    Réponses: 2
    Dernier message: 29/01/2007, 12h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo