Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Handling von Arrays in einem InterfacedObject (https://www.delphipraxis.net/205693-handling-von-arrays-einem-interfacedobject.html)

Friday 7. Okt 2020 18:56

Delphi-Version: XE3

Handling von Arrays in einem InterfacedObject
 
Hallo,
ich habe ein Datenpaket welches je nach Situation von unterschiedlichen Objekten analysiert werden soll. In diesem Datenpaket sind mehrere TArray<double> und ein paar Einzelwerte. Die ursprüngliche Idee war dies in einem InterfacedObject zu realisieren und den Objekten die diese Daten analysieren sollen nur das Interface übergeben.

beispielhaft mit nur einem Array:
Delphi-Quellcode:
IDataPackage = Interface(IInterface)
function GetMyArray1: TArray<double>;
procedure SetMyArray1(NewArray: TArray<double>);
property MyArray1: TArray<double> read GetMyArray1 write SetMyArray1;

implementation
...
procedure TSomeObject.AnalyzeData(aDataPackage: IDataPackage);
var tmpAr: TArray<double>;
i: integer;
begin
  tmpAr := aDataPackage.MyArray1;
  for i := 0 to length(tmpAr) do
    // do something with tmpAr[i]
end;
Das macht so einiges an Ärger, da immer wieder StackOverflows passieren.
Die Frage ist, wie macht man das in einer sauberen, unabhängigen und zugleich performanten Objektstruktur?

Uwe Raabe 7. Okt 2020 19:09

AW: Handling von Arrays in einem InterfacedObject
 
Da ist ein off-by-one Error:

Delphi-Quellcode:
  for i := 0 to length(tmpAr) - 1 do

Andreas13 7. Okt 2020 19:34

AW: Handling von Arrays in einem InterfacedObject
 
Oder generell, gültig für alle Arrays:
Delphi-Quellcode:
For i:= Low(tmpAr) To High(tmpAr) Do
Gruß, Andreas

stahli 7. Okt 2020 20:11

AW: Handling von Arrays in einem InterfacedObject
 
... wobei ich jetzt nicht erkennen kann, wozu ein Interface sinnvoll ist, wenn es um einen reinen Datenblock ohne eigene Logik geht.

Wäre da nicht ein Record oder eine einfache Klasse einfacher im Handling?

(Ein Argument dafür wäre natürlich die automatische Freigabe wenn der Datenblock nicht mehr in Verwendung ist. Das erkauft man sich dann halt durch die doppelte Deklaration der Klasse und des Interfaces.)

himitsu 7. Okt 2020 23:01

AW: Handling von Arrays in einem InterfacedObject
 
Wer weiß was es sonst noch in dem Interface gibt. :wink:

Tipp: Im Debugmodus vielleicht auch ab und an mal die Index- und Bereichs-Prüfungen aktivieren. :stupid:

Friday 8. Okt 2020 07:34

AW: Handling von Arrays in einem InterfacedObject
 
das fehlende "-1" war nur ein Typo hier im Beitrag.

Ja ein Record wäre vermutlich wirklich die beste Lösung in diesem speziellen Fall, da es tatsächlich nur Daten ohne Implementierung benötigt.

Aber rein akademisch bzw. für andere Situationen: Wie greift man performant auf Arrays von einem Objekt zu, dass mittels Interface übergeben wurde?
Für jedes Element über den Getter/Setter des Interface zu gehen ist keine Option.

himitsu 8. Okt 2020 08:03

AW: Handling von Arrays in einem InterfacedObject
 
Zitat:

Zitat von Friday (Beitrag 1475070)
Für jedes Element über den Getter/Setter des Interface zu gehen ist keine Option.

Warum nicht?

Delphi-Arrays:
* erstmal geht sowas natürlich in Delphi (auch wenn man ansonsten zumindestens irgendwie Lesen könnte)
* ohne ShareMem auch nur innerhalb der selben EXE (bei EXE/DLL<->DLL nur wenn mit Laufzeitpackages kompiliert)
* Die Arrays bearbeiten mit einer Referenz mit Referenzzählung, also dein Getter gibt nur einen Zeiger Zurück

* wenn man Daten (Länge, Felder usw.) geändert hat, dann muß man es an den Setter übergeben, um den eventuell geänderten Zeiger zu aktualisieren
** durch einen "Bug" (für mich ist es Einer), gibt es bei dyn. Arrays kein Copy-on-Write, so wie z.B. bei Strings (die intern auch "nur" ein dyn. Array sind)
** bei Änderung eines Chars (beim String ein Array-Element) wird vorher der ganze String kopiert ... bei nomalen dyn. Arrays passiert das nicht

Men könnte ohne Setter arbeiten und über den Getter einen Pointer rausgeben, einen Zeiger auf die Variable,
dann wäre das Array damit komplett verwaltbar (SetLength usw. geht direkt)

Delphi-Quellcode:
B := A;
B[0] := 17; // hier beim Schreibzugriff kein Copy-On-Write
if A[0] = 17 then
Ohne Copy-On-Write wird hier am Getter vorei auch "intern" das Array geändert, weil die Referenzen nicht getrennt werdeb

freimatz 8. Okt 2020 09:11

AW: Handling von Arrays in einem InterfacedObject
 
Zitat:

Zitat von stahli (Beitrag 1475060)
... wobei ich jetzt nicht erkennen kann, wozu ein Interface sinnvoll ist, wenn es um einen reinen Datenblock ohne eigene Logik geht.

Wäre da nicht ein Record oder eine einfache Klasse einfacher im Handling?

(Ein Argument dafür wäre natürlich die automatische Freigabe wenn der Datenblock nicht mehr in Verwendung ist. Das erkauft man sich dann halt durch die doppelte Deklaration der Klasse und des Interfaces.)

Bei einem Record wird der ganze Speicher kopiert, bei einem interface nur die Referenz.
Ich arbeite gerne beim Datenaustausch mit einer Datenklasse mit interface (DTO). Auf dem interface sind nur getter. Erzeugen kann man nur über eine Constructormethode. Die Datenklasse selber ist versteckt. Die doppelte Deklaration der Klasse wird erleichtert weil wir einen Code-Generator dafür haben. Man muss nur noch das interface selber angeben.

Mit Array haben wir jedoch auch da Schwierigkeiten. Ich tendiere da eher zu IList.

stahli 8. Okt 2020 11:11

AW: Handling von Arrays in einem InterfacedObject
 
@freimatz :thumb:

himitsu 8. Okt 2020 12:40

AW: Handling von Arrays in einem InterfacedObject
 
Ich hatte vor 'ner Weile mal mit einer Art "virtuellem" Interface gespielt.
Im Grunde war es ein PRecord (Pointer auf Record), nur das der Pointer in einem Interface versteckt war, samt der Referenzzählung/Speicherverwaltung und automatischem FreeMemory.

> Objekte und Interfaces sind "intern" ja auch "nur" Records, mit einem impliziten Pointer

Aber jetzt, wo Embarcadero es endlich geschaft hat die "Managed Records" einzubauen, welche wir uns seit mindestens 15 Jahren von denen gewünscht hatten,
ist sowas hinfällig und lässt sich schöner bauen > Records mit internem Pointer und automatischer Speicherverwaltung. :angle:
Oder man aber eben mit Data-Objekten und kann bei vielen Property auf auch Getter/Setter verzichten.


PS: Egal ob Interface oder Objekt, man kann auch ein Array-Property verwenden, anstatt den direkten Zugriff auf das Array (siehe Lines in der StringList),
dann ist auch eine direkte Zuweisung an ein Item möglich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:24 Uhr.
Seite 1 von 2  1 2      

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