Autor Beitrag
Wonko
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 69



BeitragVerfasst: Mo 01.10.07 13:08 
Hallo,
ich habe ein Problem, das ich lösen kann, von dem ich aber nicht weis, wieso ich es habe.
Zwei verschachtelte with-Strukturen geben mir eine EAccessViolation, wenn ich die Methoden und Eigenschaften direkt ihren Objekten zuordne klappt alles. Laut Delphi-Hilfe kann man with verschachteln, wo ist der Fehler?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
//so geht's nicht!!??
with TListBox(FindComponent('ListBox'+LBNr)) do
  for i:=Count-1 downto 0 do
    if Selected[i]=true then
      with TClientDataSet(FindComponent('CDS'+LBNr)) do
        begin
          RecNo:=ItemIndex+1;   
          Delete;
          MergeChangeLog;
          SaveToFile();
        end;

//so funktioniert es problemlos...
for i:=TListBox(FindComponent('ListBox'+LBNr)).Count-1 downto 0 do
  if TListBox(FindComponent('ListBox'+LBNr)).Selected[i]=true then
    begin
      TClientDataSet(FindComponent('CDS'+LBNr)).RecNo:=TListBox(FindComponent('ListBox'+LBNr)).ItemIndex+1;
      TClientDataSet(FindComponent('CDS'+LBNr)).Delete;
      TClientDataSet(FindComponent('CDS'+LBNr)).MergeChangeLog;
      TClientDataSet(FindComponent('CDS'+LBNr)).SaveToFile();
    end;

//LBNr ist ein String, der angibt um welche ListBox und ClientDataSet es sich handelt: '1' oder '2'

Ich hoffe, Ihr könnt mir das erklären, Dank schonmal im Voraus.
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 01.10.07 13:25 
Die TListBox in deinem äusseren with-Statement ist ja ebenfalls eine Komponente, die die Methode FindComponent kennt. Deswegen wird in dem inneren with-Statement das FindComponent der ListBox aufgerufen statt dem des Formulars. Da kommt natürlich nil zurück, so dass alles innerhalb des inneren with Zugriffsverletzungen werfen muss.

Diese netten Fehlerquellen sind der Grund, warum ich persönlich with für böse halte - wir haben hier in unseren Coding-Richtlinien die Verwendung von with verboten.

Stefan

_________________
Ein Computer ohne Windows ist wie eine Schokoladentorte ohne Senf.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19345
Erhaltene Danke: 1753

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 01.10.07 13:32 
Ich benutze with auch nicht, es bringt ja auch nix. Und es gibt noch einen anderen Grund, warum with nicht so gut ist. Beim Kompilieren wird das, was in with steht ja nur vor vor entsprechenden Befehle eingesetzt. Das heißt es wird in diesem Fall hier jedesmal wieder FindComponent aufgerufen (zumindest habe ich die Beschreibung so verstanden).
Damit ist das eine deutliche Performance-Bremse. Ich speichere in so einem Fall einfach das Objekt in eine Variable und benutze dann immer diese, womit der Code auch übersichtlicher ist, aber erstens die angesprochene Fehlerquelle nicht existiert und zweitens auch keine Performancenachteile auftreten.
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 01.10.07 14:36 
user profile iconjaenicke hat folgendes geschrieben:
Ich benutze with auch nicht, es bringt ja auch nix. Und es gibt noch einen anderen Grund, warum with nicht so gut ist. Beim Kompilieren wird das, was in with steht ja nur vor vor entsprechenden Befehle eingesetzt. Das heißt es wird in diesem Fall hier jedesmal wieder FindComponent aufgerufen (zumindest habe ich die Beschreibung so verstanden).
Damit ist das eine deutliche Performance-Bremse. Ich speichere in so einem Fall einfach das Objekt in eine Variable und benutze dann immer diese, womit der Code auch übersichtlicher ist, aber erstens die angesprochene Fehlerquelle nicht existiert und zweitens auch keine Performancenachteile auftreten.


Nein, das ist meines Wissens nicht so - with wertet den Ausdruck nur einmal aus und arbeitet mit einer verborgenen Variable. Einen Performance-Nachteil gegenüber einer expliziten Variable zum Zwischenspeichern bringt das nicht.

In dem Codebeispiel hier würde ich allerdings FindComponent gar nicht benutzen. Wenn ich etwas mit mehreren Komponenten in einem Formular machen will, speichere ich diese im FormCreate-Event in einer Liste oder einem Array und greife darüber auf die Komponente zu. Das ist erstens performanter als FindComponent, weil es die lineare Suche durch alle Komponente spart und führt ausserdem die Überprüfung, ob die Komponente überhaupt auf dem Formular existiert, schon zur Compile-Zeit durch. Bei obigem Code hagelt es dagegen sofort Zugriffsverletzungen, wenn jemand z.B. eine der Komponenten umbenennt.

Stefan

_________________
Ein Computer ohne Windows ist wie eine Schokoladentorte ohne Senf.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19345
Erhaltene Danke: 1753

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 01.10.07 15:43 
user profile iconStefan.Buchholtz hat folgendes geschrieben:
Nein, das ist meines Wissens nicht so - with wertet den Ausdruck nur einmal aus und arbeitet mit einer verborgenen Variable. Einen Performance-Nachteil gegenüber einer expliziten Variable zum Zwischenspeichern bringt das nicht.
:oops: Würde ja auch keinen Sinn machen, with xy.Create do begin..end geht ja auch...
Wonko Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 69



BeitragVerfasst: Mo 01.10.07 15:53 
Vielen Dank Euch beiden!
Auf die, ja doch simple, Erklärung hätte ich auch selber kommen können/sollen.
Werde mir die Sache mit den Variablen bzw. Listen mal durch den Kopf gehen lassen.

_________________
"Read the directions, even if you don't follow them.", Mary Schmich