Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TStringlist von function() zurückgeben - nicht möglich? (https://www.delphipraxis.net/210550-tstringlist-von-function-zurueckgeben-nicht-moeglich.html)

JanWe 10. Mai 2022 15:50

Delphi-Version: 5

TStringlist von function() zurückgeben - nicht möglich?
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo,

ich würde gerne eine Stringliste als Ergebnis einer function() zurückerhalten und ausgeben.
Das Formular hat 2 Memos und 1 Edit.

In der function werden beispielhaft erstmal nur die beiden Strings aneinandergehängt.

Erst hat Delphi gemeckert, weil der Zugriff bei der Übergabe an Result in der Funktion oder dann im Button bei der Zuweisung an Zielliste nicht möglich war, (ich hab wegen der Übersicht wieder v verwendet; dürfte aber wegen assign() egal sein)

aktuell crasht es schon beim Verlassen der Buttonprozedur nach v.free.

Es ist mir ein Rätsel.

Was mach ich denn alles falsch?

Delphi-Quellcode:
function sende (sa: TStringlist; sb: TStringlist): TStringlist;
var
x : Tstringlist;
begin
x := Tstringlist.create;
x.add( sa[0] + Sb[0] );
 form1.memo1.lines.Assign(x); // Testweise ausgeben - funktioniert

{ welches der folgenden beiden? }
// result := (z); geht ja auch nicht
//result.Assign(z);
  x.free;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
u : Tstringlist;
v : Tstringlist;
begin
 u := Tstringlist.create;
 v := Tstringlist.create;

 u.add('Hafen');
 u.add('Donau');

 v.add('schiffahrt'); v.add('rundfahrt');

 v := sende (u, v);
//  v.Assign( sende (u, v) ); // geht irgendwie auch nicht

// memo2.lines.Assign(v); // hier gibt's nen Knall
 u.free;
 v.free;
end;
Angehängt: Sende.7z (126,7 KB)

mkinzler 10. Mai 2022 15:53

AW: TStringlist von function() zurückgeben - nicht möglich?
 
Auf die lokale Variable kannst Du verzichten.
Du gibst die Stringliste ja frei. Da ist es nur folgerichtig, dass es knallt.

Delphi-Quellcode:
function sende (sa: TStringlist; sb: TStringlist): TStringlist;
[s]var
x : Tstringlist;[/s]
begin
result := Tstringlist.create;
result.add( sa[0] + Sb[0] );
 form1.memo1.lines.Assign(result); // Testweise ausgeben - funktioniert

{ welches der folgenden beiden? }
// result := (z); geht ja auch nicht
//result.Assign(z);
 [s] x.free;[/s]
end;

JanWe 10. Mai 2022 15:55

AW: TStringlist von function() zurückgeben - nicht möglich?
 
achso, nee, das soll alles x

hatte die Liste 'z' umbenannt in 'x' (naja, der Buchstabe 'z' ist jetzt derzeit gerade "nicht so beliebt", darum dachte ich 'x' wäre besser.

Edit:
Aber warum soll ich die lokale Stringliste nicht verwenden und nach Überagbe an Result (wie mach ich das? doch mit Assign, oder?) löschen?

Ich würde die gerne mit/an result übergeben. (das mit form1.memo war nur testweise gedacht)
Oder gehen da nur Strings und Zahlen?
also result.assign(x); dann x.free;

mkinzler 10. Mai 2022 15:58

AW: TStringlist von function() zurückgeben - nicht möglich?
 
Der Name ist ja egal. Du darfst das Ergebnis halt nicht vor der Rückgabe freigeben. Man kann direkt mit result arbeiten.

JanWe 10. Mai 2022 16:10

AW: TStringlist von function() zurückgeben - nicht möglich?
 
ja, ich habe ja am Ende der function versucht result <-- x zuzuweisen,

result.assign(x);

aber dann crashte es bei der Rückkehr zum Button.


Delphi-Quellcode:
function sende (sa: TStringlist; sb: TStringlist): TStringlist;
var
x : Tstringlist;
begin
x := Tstringlist.create;
x.Clear;
x.add( sa[0] + Sb[0] );


{ welches der folgenden beiden? }
// result := (z); geht ja auch nicht, oder? wird ja dann nur als String zugwiesen

result.Assign(x); // <-- knallt aktuell hier. Keine Ahnung, warum
  x.free;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
u : Tstringlist;
v : Tstringlist;
begin
 u := Tstringlist.create;
 v := Tstringlist.create;

 u.add('Hafen');
 u.add('Donau');

 v.add('schiffahrt'); v.add('rundfahrt');


 v.Assign( sende (u, v) );

 u.free;
 v.free;
end; // ende Button

mkinzler 10. Mai 2022 16:31

AW: TStringlist von function() zurückgeben - nicht möglich?
 
Zitat:

Du darfst das Ergebnis halt nicht vor der Rückgabe freigeben.
und genau das machtst Du

Zitat:

Delphi-Quellcode:
x.free;

Einfach so:

Delphi-Quellcode:
function sende (sa: TStringlist; sb: TStringlist): TStringlist;
begin
  result := Tstringlist.create;
  result.add( sa[0] + Sb[0] );
  form1.memo1.lines.Assign(result); // Testweise ausgeben - funktioniert
end;

JanWe 10. Mai 2022 16:40

AW: TStringlist von function() zurückgeben - nicht möglich?
 
achso, ich dachte, result passt sich dem an, was ich hinter der Function deklariere.
Dachte, das würde dann die Stringlist aufnehmen.

jaenicke 10. Mai 2022 17:41

AW: TStringlist von function() zurückgeben - nicht möglich?
 
Du arbeitest bei Objekten immer mit Pointern. Du gibst also nur die Adresse des Objektes zurück. Wenn das dann zerstört ist, kannst du damit auch nichts mehr anfangen.

Deshalb gibt man auch keine Objekte zurück. Erstellung und Freigabe eines Objekts sollten immer spiegelverkehrt an der gleichen Stelle passieren. (oben in einer Methode - weiter unten in der gleichen Methode, Konstruktor - Destruktor, ...)

Hier geht das dann so:
Delphi-Quellcode:
procedure FillMyList(const AList: TStrings);
begin
  AList.Add('A');
  AList.Add('B');
end;

// Verwendung:
var
  Test: TStringList;
begin
  Test := TStringList.Create;
  try
    FillMyList(AList);
    ShowMessage(AList[0]);
  finally
    Test.Free;
  end;
end;

Redeemer 10. Mai 2022 19:08

AW: TStringlist von function() zurückgeben - nicht möglich?
 
In Delphis eigenem Quelltext werden Argumente niemals als const deklariert, bei denen eine Klasse übergeben wird. Ist für Typen, die nicht größer sind als Pointer/NativeInt aber nicht so wichtig.

Ansonsten ist jaenickes Antwort richtig: Objekte wird man i.a.R. nicht in Funktionen zurück. Davon gibt es zwei Ausnahmen:
* Getter einer Klasse (Funktionen, die eine Eigenschaft zurückgeben). Der Speicher des zurückgegebenen Objekts wird weiterhin von der Klasseninstanz des Getters verwaltet, weshalb man das Ergebnis des Getters nicht selbst freigeben darf. Kennt man von TListBox.Items, TMemo.Strings, TComboBox.Items.
* Konstruktoren. Dann heißt das Ergebnis nicht Result (oder Methodenname) sondern Self (kann man auch weglassen):
Delphi-Quellcode:
type TMeineStringList = class(TStringList)
  constructor Create(sa, sb: TStringList);
end;

constructor TMeineStringList.Create(sa, sb: TStringList);
begin
  inherited Create();
  Self.Add(sa[0] + sb[0]);
end;

jaenicke 10. Mai 2022 20:06

AW: TStringlist von function() zurückgeben - nicht möglich?
 
Zitat:

Zitat von Redeemer (Beitrag 1505678)
In Delphis eigenem Quelltext werden Argumente niemals als const deklariert, bei denen eine Klasse übergeben wird. Ist für Typen, die nicht größer sind als Pointer/NativeInt aber nicht so wichtig.

Ich finde es generell sinnvoll, weil man dann nicht aus Versehen die übergebene Variable überschreibt, auch wenn das nur lokale Auswirkungen hätte.

Billa 11. Mai 2022 12:11

AW: TStringlist von function() zurückgeben - nicht möglich?
 
Nur mal ganz schnell rausgehauen: um eine Stringlist zu übergeben, könnte "DelimitedText" helfen.

Function BlaBla(a, b : TStrings): string;
begin
SList := TStringList.Create;
try
SList.Delimiter := '|';
SList.StrictDelimiter := true;

// hier die Manipuilationen der Ergebnisliste

SList.Add( a[0]+b[0] );
....

ResultStr := SList.DelimitedText;
finally
SList.Free;
end
Result := ResultStr;
end

und "auf der anderen Seite" wieder in eine Liste umwandeln

SList := TStringList.Create;
try
SList.Delimiter := '|';
SList.StrictDelimiter := true;
SList.DelimitedText := XXX;

// Hier der Zugriff auf die Elemente aus SList

finally
SList.free;
end

Dann ist die Rückgabe ein String. Man muss sich halt nur einen guten "Delimiter" ausdenken, der garantiert nicht in den Werten vorkommt. Ich verwende gern "|", weil Komma, Semikolon und ähnliches gerne mal in den Werten steht. Das ist natürlich nicht das schnellste, ist sicher nicht optimal und taugt auch nur bei begrenzten Mengen, vermeidet aber die oben erwähnten Gefahren und ist einfach einzusetzen

bernau 11. Mai 2022 13:17

AW: TStringlist von function() zurückgeben - nicht möglich?
 
Bei der "const"-Debatte verweise ich mal auf diesen Link

Pauschal verwende ich const bei jedem Parameter. Schadet nicht und im Zweifel vergesse ich es nicht bei Typen, bei denen es durch den const-Parameter eine Optimierung gibt.

himitsu 11. Mai 2022 21:54

AW: TStringlist von function() zurückgeben - nicht möglich?
 
Ja, natürlich darf man das Objekt (TStringList) nicht intern freigeben, wenn man sie zurückgeben will.
Aber dann muß man auch dafür sorgen, dass der Aufrufer die Liste freigibt.

Ist aber auch "unschön", weil man ohne gute Dokumentation nie weiß, ob das Result einer aufgerufenen Methode freigegeben werden muß, oder nicht.
Darum sollte man besser den Namen der Methode so wählen, damit daraus erkennbar ist, dass diese Liste "erstellt" wird. (z.B. Create im Name)

Alternativ speichert man sich das Result intern (global) und gibt sie dann später frei.
Hier wird es dann spaßig, wenn gleichzeitig mehrere Rückgaben dieser Methode verwendet werden sollen. (vor allem, wenn dann alles immer die Selbe Liste zurückgibt und somit der vorherige Aufruf ungültig würde)

Sicherheitshalber machen es daher Viele so, dass man die Liste rein gibt, welche gefüllt werden soll.



Ansonsten:

* z.B. eine IStringList, IStrings oder sowas als Rückgabe, da Interfaces mit automatischer Freigabe

* bzw. ich verwende für sowas ein TArray<string> als Result
* * wird automatisch Speicherverwaltet
* * und wenn der Aufrufer es braucht, kann er es direkt in ein For-In geben, oder in eine eigene StringList per AddStrings übernehmen


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:24 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz