![]() |
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:
Das macht so einiges an Ärger, da immer wieder StackOverflows passieren.
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; Die Frage ist, wie macht man das in einer sauberen, unabhängigen und zugleich performanten Objektstruktur? |
AW: Handling von Arrays in einem InterfacedObject
Da ist ein off-by-one Error:
Delphi-Quellcode:
for i := 0 to length(tmpAr) - 1 do
|
AW: Handling von Arrays in einem InterfacedObject
Oder generell, gültig für alle Arrays:
Delphi-Quellcode:
Gruß, Andreas
For i:= Low(tmpAr) To High(tmpAr) Do
|
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.) |
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: |
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. |
AW: Handling von Arrays in einem InterfacedObject
Zitat:
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:
Ohne Copy-On-Write wird hier am Getter vorei auch "intern" das Array geändert, weil die Referenzen nicht getrennt werdeb
B := A;
B[0] := 17; // hier beim Schreibzugriff kein Copy-On-Write if A[0] = 17 then |
AW: Handling von Arrays in einem InterfacedObject
Zitat:
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. |
AW: Handling von Arrays in einem InterfacedObject
@freimatz :thumb:
|
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 08:01 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 by Thomas Breitkreuz