IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

XE2 - TStringList + object


Sujet :

Langage Delphi

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2015
    Messages : 76
    Points : 25
    Points
    25
    Par défaut XE2 - TStringList + object
    Bonjour,

    Je suis occupé à tester les TStringList.
    J'aimerais avoir votre avis.

    Premier cas, j'ai créé une method TStudent
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    type
      TStudent = class
        name: string;
        firstname: string;
        year: integer;
      private
      public
      end;
    Et sur un bouton je place le code ci-dessous
    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
    28
    29
    30
    procedure Tform_index.btn_TStringLIstObjectClick(Sender: TObject);
    var
      listStudent: TStringList;
      student: Tstudent;
      index: Integer;
    begin
      listStudent := TStringList.Create;
      listStudent.Sort;
     
      student := Tstudent.Create();
      student.name := 'Craparof';
      student.firstName := 'Etienne';
      listStudent.AddObject(student.name, student);
     
      //index value 1
      student := Tstudent.Create();
      student.name := 'John';
      student.firstName := 'Doe';
      student.year := 34;
      listStudent.AddObject(student.name, student);
     
    if listStudent.Find('Craparof', index) then
      begin
        //je veux rajouter l'age pour craparof
        student := listStudent.Objects[index] as Tstudent;
        student.year := 54;
        listStudent.Objects[index] := student;
      end
      else
        OutputDebugString('Not found');
    Je voudrais rajouter à la volée l'âge pour Craparof, je voulais utiliser listStudent.Objects[index].year mais il ne connait pas la valeur.
    Du coup j'ai utilisé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    student := listStudent.Objects[index] as Tstudent;
        student.year := 54;
        listStudent.Objects[index] := student;
    Mais je trouve que c'est assez lourd.
    Y a t'il une autre façon d'y arriver ?

    Merci pour vos conseils

    Bertrand

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    392
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 392
    Points : 635
    Points
    635
    Par défaut
    la ligne listStudent.Objects[index] := student; est inutile

    tu peux faire un TStudent(listStudent.Objects[index]).year := 54; mais il faut vraiment être sur que l'objet existe et que ce soit un TStudent

    sinon tu peux utiliser les génériques

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2015
    Messages : 76
    Points : 25
    Points
    25
    Par défaut
    Bonjour exoseven,

    Effectivement la ligne listStudent.Objects[index] := student; n'est pas nécessaire Mais pourquoi.
    Dans ma tête je voulais directement modifier la valeur dans la stringLIst via listStudent.Objects[Index].year, merci pour ton conseil TStudent(listStudent.Objects[index]).year := 57;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    student := listStudent.Objects[index] as Tstudent;
    student.year := 54;
    listStudent.Objects[index] := student; //non nécessaire
    Mais comment es-ce que cela fonctionne ?
    Pour moi quand je fais student := listStudent.Objects[index] as Tstudent; je crée un doublon de Craparof, puis je le repousse dans ma stringList via listStudent.Objects[index] := student;

    Merci pour ton aide.

    Bertrand

  4. #4
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 490
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 490
    Points : 2 752
    Points
    2 752
    Billets dans le blog
    10
    Par défaut
    Citation Envoyé par beletot
    ...
    listStudent.Objects[index] := student; n'est pas nécessaire Mais pourquoi.
    Dans ma tête je voulais directement modifier la valeur dans la stringLIst via listStudent.Objects[Index].year, merci pour ton conseil TStudent(listStudent.Objects[index]).year := 57;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    student := listStudent.Objects[index] as TStudent;
    student est en fait un pointeur sur l'objet créé en mémoire.

    Le symbole ^ déréférence le pointeur, c'est-à-dire qu'il renvoie la valeur stockée à l'adresse mémoire contenue dans le pointeur. Le compilateur déréférence automatiquement lorsque cela est judicieux pour un objet qui est adressé sans utiliser ‘^’. Ce mécanisme est fourni de base par Delphi lorsque vous utilisez des objets qui sont déclarés avec le mot réservé class. Ce mécanisme permet d’utiliser les pointeurs de façon transparente. En fait, dans Delphi, l’identifiant de ce type d'objet est un pointeur. Le fait de déclarer une variable de type Class déclare en fait un pointeur. Ensuite la méthode Create alloue l’espace mémoire nécessaire à l’objet créé et stocke l’adresse de cet espace dans ce pointeur.
    On travaille donc sur l'original et non sur une copie
    "student.year := 54;" signifie donc à L'adresse donné par le pointeur Studend d'un objet de type Tstudent je charge la variable Year avec la valeur 54
    Donc comme on travaille sur l'original pas besoin de sauvegarde

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2015
    Messages : 76
    Points : 25
    Points
    25
    Par défaut
    Merci pour la réponse.

    Je n'avais pas pensé au principe de pointer.
    Tout de suite c'est plus logique.

    Je vais continuer mes tests sur des stringList.
    Comparer deux string list.

  6. #6
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    à mon avis c'est surtout une fausse bonne idée de stocker tes objets dans un TStringList

    voir par exemple TObjectList
    http://docwiki.embarcadero.com/CodeE...tList_(Delphi)
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2015
    Messages : 76
    Points : 25
    Points
    25
    Par défaut
    Bonjour Paul,

    Je viens de faire un test avec une TObjectList, bon au final pour moi c'est la même chose.
    Textuellement il semble plus logique d'utiliser une TObjectList pour y placer un object.
    Mais pourquoi est'il déconseillé d'utiliser une TStringList ?

    De mon coté je vois juste que cela passe avec une TStringList et une TObjectList

    Bertrand

  8. #8
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 418
    Points : 5 816
    Points
    5 816
    Par défaut
    salut

    tout simplement parce que leTObjectList s'occupe de la liberation de l'objet au moment où tu fait le delete et à sa destruction
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2015
    Messages : 76
    Points : 25
    Points
    25
    Par défaut
    Citation Envoyé par anapurna Voir le message
    salut

    tout simplement parce que leTObjectList s'occupe de la liberation de l'objet au moment où tu fait le delete et à sa destruction
    Bonjour anapurna,

    Okay, je note la coup de la libération.

    Bon là je bloque, avec une stringList j'utilisais myStringList.find('robert',index), pas de find avec TObjectList, je vais donc vers indexOf, pas moyen de lui donner la bonne syntax :-(
    Je me base sur le code du lien ci-dessus.
    http://docwiki.embarcadero.com/CodeE...t_%28Delphi%29

    Il attends un objet ? Mais pourquoi ?

    Bertrand

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Cela me parait assez évident .

    Avec un TStringList on stocke des chaînes de caractères. Et comparer 2 chaînes, à l'Unicode près, c'est assez simple.

    Avec un TObjectList on stocke des objets. (ce sont plus des pointeurs).
    Comment veux-tu que cette classe sache à l'avance comment comparer 2 objets? En C++ on peut surcharger les opérateurs dont l'opérateur ==.

    Dans ce cas, il faut parcourir ta liste et faire une méthode de comparaison bool compare(const TMyObject& other);.

    Après, on peut rechercher un objet avec son adresse mémoire.
    Mais si c'est un tableau dynamique, les pointeurs peuvent changer pendant la réallocation de la liste lors de l'ajout/ suppression de certains éléments.
    À moins que TObjectList arrive à faire sans réallocation (via une liste chaînée par exemple).

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2015
    Messages : 76
    Points : 25
    Points
    25
    Par défaut
    Okay,

    Dans ce cas là la recherche est moins rapide/facile

    Sous PHP voici ce que je fais.
    J'ai une query dans une table personne.

    Je gère le retour de la db sous cette forme.
    J'ai un array
    array[denis] = object personne.myname = denis, personne.myFistname = blabla1
    puis une autre personne
    array[marcel] = object personne.myname = marcel, personne.myFistname = blabla2

    Je peux facilement savoir si j'ai un denis dans mon retour.

    J'essaye de faire la même chose sous Delphi.

    Je viens de voir qu'il y a avait une method TDictionary
    Es-ce plus pratique pour ce que je voudrais faire ?

    Je pourrais également utiliser une arrayList ?

    Bertrand

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    TStudent c'est une classe pas une méthode
    Idem TDictionary c'est une classe

    Citation Envoyé par beletot Voir le message
    Il attends un objet ? Mais pourquoi ?
    Parce que le Delphi est un langage très fortement typé contrairement au PHP
    Sauf qu'avec les génériques, le fort typage devient plus difficile à appréhender mais il est toujours là lors de la spécialisation de la générique

    En PHP, tu peux avoir un contrôle de type, par exemple sur une fonction tu peux spécifier la classe d'un paramètre, je t'invite a consulter la page Manuel PHP ›Référence du langage ›Les classes et les objets ›Typage Objet
    En Delphi, c'est tout le temps typé !
    Il te faut bien appréhender ce principe !

    Du coup, il faut savoir lire la documentation
    Et comme tu ne sembles pas maitriser le fait qu'un objet est une référence (un pointeur),
    il semble normal que tu dois dérouter par le IndexOf de la TObjectList et encore plus avec la couche générique

    Attention il existe deux TObjectList
    - System.Generics.TObjectList
    function IndexOf(const Value: T): Integer;
    Le T c'est forcément un TObject
    Normalement, tu aurais du déclarer System.Generics.TObjectList<TStudent>;
    et le compilateur va générer une méthode
    function IndexOf(const Value: TStudent): Integer;
    Et c'est pour cela que le compilateur à réclamer un TStudent pour ton IndexOf et refusé le type string car TStudent joue le role de T
    Générique mais fortement typé !

    - System.Contnrs.TObjectList
    function System.Contnrs.TObjectList.IndexOf(AObject: TObject): Integer;
    Avec cette syntaxe, tu aurais tu de suite vu que cela réclame un TObject, en gros cela cherche juste le pointeur dans la liste

    Le gros avantage de la System.Generics.TObjectList
    c'est que l'on peut écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    StudentList.Items[I].Year := 72;
    alors qu'avec System.Contnrs.TObjectList
    il faut écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    (StudentList.Items[I] as TStudent).Year := 72;

    La TStringList, depuis Delphi 2009, je crois, gère le OwnsObjects

    la TStringList pour simuler un tableau associatif PHP, ca fonctionne
    Effectivement pour stocker des objets, la TObjectList est souvent un meilleur sauf si as besoin d'un index texte

    Dans ton cas l'index texte c'est le nom, ce n'est pas un très bon index mais c'est ton choix
    la TStringList suffit pour un projet scolaire.

    Le nom de famille n'est pas forcément une clé unique, tu pourrais avoir plusieurs DUPONT
    la TStringList accepte les doublons selon la valeur de Duplicates

    tu peux aussi utiliser le System.Generics.Collections.TObjectDictionary<string, Tstudent>
    le TObjectDictionary c'est comme le TDictionary mais gère un doOwnsValues pour une libération automatique
    C'est un peu plus moderne, mais cela ne change pas grand chose.
    Le gros avantage est le même qu'avec la TObjectList, c'est le transtypage implicite de l'objet grâce au générique.
    TObjectDictionary n'accepte pas les doublons

    Pour un projet professionnel, on va plutôt créer un type de liste dediée (soit par héritage soit par encapsulation) avec ses propres méthodes IndexOfNom, IndexOfPrénom ...
    Très vite cela peut devenir pénible pour les recherches multi-champs
    et dans ce cas un DataSet et sa méthode Locate ou la propriété Filter c'est plus pratique

    Pour ma part, la seule fois où j'utilise Objects d'un TStrings c'est parce que c'est lié à un TComboBox, TListBox ...
    Le TObjectDictionary, TObjectList ... c'est plutôt lié à du code technique
    Tout le reste c'est à base de DataSet, et j'ai des classes ORM qui encapsule les DataSet pour les utiliser comme des classes Entité un peu comme ton TStudent
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  13. #13
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2015
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2015
    Messages : 76
    Points : 25
    Points
    25
    Par défaut
    Bonjour ShaiLeTroll,

    Merci pour ta réponse, là j'ai bien failli y laisser des neurones.

    En PHP, tu peux avoir un contrôle de type, par exemple sur une fonction tu peux spécifier la classe d'un paramètre, je t'invite a consulter la page
    Je ne connaissais pas cette option. Merci

    Et comme tu ne sembles pas maitriser le fait qu'un objet est une référence (un pointeur),
    Je comprends le principe mais j'ai dur à l'appliqué pour le moment.

    Dans ton cas l'index texte c'est le nom, ce n'est pas un très bon index mais c'est ton choix
    la TStringList suffit pour un projet scolaire.
    Oui c'était un exemple, dans la cas réel j'utilise un clef unique.

    Je viens d'essayer le TDictionary, c'est assez pratique. J'arrive facilement à l'utiliser.
    Je vais voir pour le TObjectDictionary.

    Pour le dataset ce sera sans doute quand j'aurai plus de temps.

    Un grand merci pour ton temps.

    Bonne journée

    Bertrand

Discussions similaires

  1. [Débutant] TStringList en XE2
    Par Mercusyo dans le forum C++Builder
    Réponses: 2
    Dernier message: 27/03/2012, 09h02
  2. [TStringList] Objects et record
    Par Pedro dans le forum Langage
    Réponses: 5
    Dernier message: 28/07/2004, 13h52
  3. Comment bien gerer la mémoire avec les TStringList?
    Par david_chardonnet dans le forum Langage
    Réponses: 5
    Dernier message: 18/06/2003, 09h57
  4. TStringList en array of string
    Par JediKerian dans le forum Langage
    Réponses: 2
    Dernier message: 20/03/2003, 15h37
  5. TStringList
    Par giaco dans le forum Composants VCL
    Réponses: 3
    Dernier message: 17/09/2002, 13h50

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