Avatar billede kennethjohnsen Nybegynder
04. august 2008 - 10:43 Der er 11 kommentarer og
1 løsning

Debugging af TObjectList

Jeg har en variabel som er en TObjectList. Når man tilføjer den til watch-vinduet, kan man ikke se elementerne i den.
Det er vel meget naturligt, da debuggeren ikke kan vide hvilke slags objekter der er i den.

Men kan man tvinge debuggeren til at tolke dem som en bestemt objekt-type? Jeg ved at alle objekterne er samme type.

Jeg kan selvfølgelig caste:

TDataElement(MinListe[1])

Men da jeg ikke ved hvor mange elementer der er, bliver det bøvlet.

Hvordan med næste version af Delphi? Den får jo generics, så måske kunne man forestille sig at:

TList<TData>

er nemmere for debuggeren at vise?
Avatar billede hrc Mester
04. august 2008 - 11:52 #1
En rettelse til dit spørgsmål: Det kaldes ikke variabel, det er en instans af en klasse: en objektinstans.

Du kan overstyre TObjectList.Items:
    ...
  public
    property Items[const aIndex: integer]: TMyProject read GetItems; default;

GetItems ser sådan ud:

function TMyObjectList.GetItems(const aIndex: integer): TMyProject;
begin
  result := inherited Items[aIndex] of TMyProject;
end;
Avatar billede hrc Mester
04. august 2008 - 11:53 #2
Rettelse igen:

  result := inherited Items[aIndex] as TMyProject;
Avatar billede kennethjohnsen Nybegynder
04. august 2008 - 21:23 #3
Tak for tipsene. Det vil jeg prøve i morgen.

Men jeg er ikke enig mht. variabel/instans:

var
  minListe : TObjectList;

Her kan vi vist være enige om at "minListe" er en variabel. Den er endnu ikke en instans af TObjectList.
At den så senere kommer til at indeholde/pege på en instans af TObjectList, er noget andet.

Men det er variablen (i dette tilfælde "minListe"), som man tilføjer til watch-vinduet. Den kan jo i princippet være NIL, og altså ikke indeholde/pege på nogen instans.
Avatar billede hrc Mester
05. august 2008 - 09:11 #4
Har altid anset variable værende statiske datatyper (integers, records og lignende), mens objekter er noget dynamisk som man opretter og opbevarer i en ... objektinstansvariabel (skjult pointer). Man, som du skriver, bliver det ikke en instansvariabel før det tildeles et objekt. Indtil da kan man meget vel kalde det en variabel.

"I stand corrected"
Avatar billede kennethjohnsen Nybegynder
05. august 2008 - 13:16 #5
Det kan jeg ikke få til at virke.
Lige meget hvad jeg tilføjer til watch-vinduet, viser den bare "()"
Her er et lille test-program jeg har lavet.

unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Contnrs;

type
  { Data-elementer til listen }
  TData = class(TComponent)
  private
    FFirstName: String;
    procedure SetFirstName(const Value: String);
  published
    property FirstName : String read FFirstName write SetFirstName;
  end;

  { Min egen liste-klasse }
  TMyObjectList = class(TObjectList)
  private
    function GetItems(const aIndex: integer): TData;
  public
    property Items[const aIndex: integer]: TData read GetItems; default;
  end;

  { Formen }
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TData }

procedure TData.SetFirstName(const Value: String);
begin
  FFirstName := Value;
end;

{ TMyObjectList }

function TMyObjectList.GetItems(const aIndex: integer): TData;
begin
  result := inherited Items[aIndex] as TData;
end;

{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
  aData : TData;
  aList : TMyObjectList;
  I : Integer;
begin
  try
    aList := TMyObjectList.Create;
    aList.OwnsObjects := True;

    aData := TData.Create(Self);
    aData.FirstName := 'Ole';
    aList.Add(aData);

    aData := TData.Create(Self);
    aData.FirstName := 'Bent';
    aList.Add(aData);

    {
      Når man når hertil burde man kunne se en liste med to TData-objekter i,
      men debuggerens watch-vindue viser bare:

      aList      ()

      Jeg har også prøvet at tilføje aList.Items til watch-vinduet,  men uden held.
    }
  finally
    aList.Free;
  end;

end;

end.
Avatar billede hrc Mester
05. august 2008 - 15:34 #6
Så tror jeg ikke det kan lade sig gøre. Bruger ikke Watches meget. Foretrækker at holde musen over "variablen" når jeg debugger. Klikker man på det lille plus kan man se hele strukturen.
I øvrigt er det sjældent man laver en "aList[1]", men har det i en løkke - og så kan du skrive aList[i] og se objekterne et efter et.

Mht. din form spotter jeg en almindelig fejl:
Create skal stå før din try. Linjen "aList.Free;" vil fejle hvis objektet ikke oprettes korrekt.

  aList := TMyObjectList.Create;
  try
    ...
  finally
    aList.Free;
  end;
Avatar billede hrc Mester
05. august 2008 - 15:38 #7
Højreklikker man på sit "Watch" kan man vælge menupunktet "Inspect" hvorved du måske får det du ønsker.
Avatar billede hrc Mester
05. august 2008 - 15:41 #8
Inde i Inspect-dialogen kan du yderligere typecaste "Items" med "TData" og så har du attributterne.
Avatar billede kennethjohnsen Nybegynder
05. august 2008 - 15:48 #9
OK. Det vil jeg prøve, men det kan da godt være at en objekt-liste er for kompleks til at debuggeren kan kigge ind i den.

Mht. at kigge på aList[i] vil det også være OK. Det ville bare være smartere at kunne lade indlæsningen af TData objekter blive færdig, og så kunne folde hele strukturen ud i watch-vinduet.

Det kan man f.eks. i Smalltalk, som har rimeligt gode introspection muligheder. Måske kan man også i Java (det burde man kunne).

Jeg prøver med de tips du har givet. Ellers kan jeg jo altid få strukturen skrevet ud i en log-fil eller lignende.

Smid lige et svar hvis du vil have pointene.
Avatar billede hrc Mester
05. august 2008 - 17:48 #10
Jeg vil gerne have points men kun hvis jeg har kunnet hjælpe.
Avatar billede hrc Mester
05. august 2008 - 17:49 #11
Hvis du vil skrive noget til en fil har Delphi gode værktøjer udi RTTI, så man kan evt. frembringe en generisk funktion der kan logge objektets data til en fil/stream
Avatar billede kennethjohnsen Nybegynder
05. august 2008 - 19:37 #12
Ja. Det tænkte jeg også. Jeg har fundet noget om RTTI i en gammel Delphi-bog jeg har liggende, så jeg prøver at strikke noget sammen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester