Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   TArray<string> als const im Record deklarieren (https://www.delphipraxis.net/202760-tarray-string-als-const-im-record-deklarieren.html)

DieDolly 5. Dez 2019 13:16

Delphi-Version: 10.3 Rio

TArray<string> als const im Record deklarieren
 
Gab es das nicht mal früher? Konnte man
Delphi-Quellcode:
const
 X: array[0 .. 1] of string = ('1', '2');
nicht mal irgendwie mit TArray<string> deklarieren?
Delphi-Quellcode:
const
 X: TArray<string>('1', '2');
Wie macht man es richtig?

Warum?
Ich habe eine Funktion, die TArray<string> entgegennimmt. Und X als Parameter nimmt sie nicht, da es array of string ist.
Folglich müsste ich also den Funktionskopf zu array of string umschreiben. Kein Großes Problem, aber inkonsistent am Ende, wenn man nur noch TArray<string> verwendet.

Andreas13 5. Dez 2019 13:23

AW: TArray<string> als const deklarieren
 
array[0 .. 1] of string ist ein statisches Array, TArray<string> ist dagegen ein dynamisches Array mit einer Länge von 0 bei der Deklaration. Bevor Du den Inhalt reinpackst, muß Du mit SetLength(..) die Länge einstellen. Erst danach kännen die Elemente belegt werden. Deswegen geht die Const-Deklaration nicht.
Gruß, Andreas

DieDolly 5. Dez 2019 13:33

AW: TArray<string> als const deklarieren
 
Ich dachte immer das geht so auch irgendwie

https://stackoverflow.com/questions/...22929#25622929

Delphi-Quellcode:
const
  MyArray: TArray<String> = ['First','Second','Third'];

Daniel 5. Dez 2019 13:34

AW: TArray<string> als const deklarieren
 
Du hast die Lösung da doch selbst verlinkt.

DieDolly 5. Dez 2019 13:37

AW: TArray<string> als const deklarieren
 
Zitat:

[dcc32 Fehler] F.pas(263): E2086 Typ 'TArray<T>' ist nicht vollständig definiert
Das scheint wohl nicht so zu funktionieren. Nur ohne Record
Delphi-Quellcode:
type
 TRec = record
 const
  MyArray: TArray<String> = ['First','Second','Third'];
end;

Dennis07 5. Dez 2019 15:04

AW: TArray<string> als const deklarieren
 
Zitat:

Zitat von DieDolly (Beitrag 1452822)
Zitat:

[dcc32 Fehler] F.pas(263): E2086 Typ 'TArray<T>' ist nicht vollständig definiert
Das scheint wohl nicht so zu funktionieren. Nur ohne Record
Delphi-Quellcode:
type
 TRec = record
 const
  MyArray: TArray<String> = ['First','Second','Third'];
end;

Das ist ein Bug im Compiler, der nach wie vor verhindert, generische Arrays in Klassen oder Records zu verwenden.
Siehe hierzu RSP-21151. Wurde bisher nicht gefixt. Ob es zu den Bugs wird, die uns wohl für ewig erhalten bleiben werden, lässt sich nur vermuten. Es existiert seit es Generics gibt und wurde bereits vor fast anderthalb Jahren gemeldet.

Derzeit bleibt dir wohl nichts anderes übrig, als es entweder lokal in einer Methode, global in einer Unit, oder als normales statisches/dynamisches Array zu deklarieren.

Zitat:

Zitat von DieDolly (Beitrag 1452813)
Ich habe eine Funktion, die TArray<string> entgegennimmt. Und X als Parameter nimmt sie nicht, da es array of string ist.
Folglich müsste ich also den Funktionskopf zu array of string umschreiben. Kein Großes Problem, aber inkonsistent am Ende, wenn man nur noch TArray<string> verwendet.

Erstens kannst du beide auch inline mit
Delphi-Quellcode:
['value1', 'value2']
deklarieren.
Zweitens sind
Delphi-Quellcode:
TArray<String>
und
Delphi-Quellcode:
array of String
zuweisungskompatibel, bzw. explizit umwandelbar:

Delphi-Quellcode:
var
  a1: array of String;
  a2: TArray<String>;
begin
  a1 := a2; // Geht nicht
  a2 := a1; // Geht nicht
  TArray<String>(a1) := a2; // Geht
  a2 := TArray<String>(a1); // Geht
end;
Und, drittens, sind Parameter eines Array-Typs überhaupt keine echten "Array"-Parameter, sondern so genannte "offene Array-Parameter".
Deshalb kannst du ihnen eigentlich jeden Array-Typen, inklusive konstanter, statischer,
Delphi-Quellcode:
TArray<T>
,
Delphi-Quellcode:
TMyArray
und
Delphi-Quellcode:
array of TMy
übergeben, ohne dass der Compiler rummeckert. Innerhalb der Funktion werden sie dann (nicht wie
Delphi-Quellcode:
TArray<T>
-Parameter!) als Array-Objekte, sondern als Kopien dieser verwendet.
Das heißt, selbst, wenn du das Array-Objekt in der Funktion veränderst (zB. ein Element veränderst), bleibt das Ursprungsarray gleich.

Wenn du mehr über offene Arrays wissen willst, habe ich dazu einen ausführlichen Post vor einiger Zeit geschrieben. Du findest ihn hier.

DieDolly 5. Dez 2019 16:30

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Das ist ein Bug im Compiler, der nach wie vor verhindert, generische Arrays in Klassen oder Records zu verwenden.
Na super. Dann wird der woh ewig bleiben.

Uwe Raabe 5. Dez 2019 16:42

AW: TArray<string> als const im Record deklarieren
 
Man kann aber auch einfach mal ganz pragmatisch dem Compiler auf die Sprünge helfen. Das ist vermutlich effizienter als auf einen Fix zu warten:

Delphi-Quellcode:
type
  TStringArray = TArray<string>;

type
  TRec = record
  const
    MyArray: TArray<String> = ['First', 'Second', 'Third'];
  end;
Interessant dabei ist, daß man den Alias gar nicht verwenden muss...

himitsu 5. Dez 2019 17:56

AW: TArray<string> als const im Record deklarieren
 
Warum muß diese Konstante denn ein dynamisches Array und kann nicht statisch sein? (OK, bei Zuweisung an ein dynamisch Array muß dann umkopiert werden)

Kann Delphi nicht auch inzwischen bei statischen Arrays die Länge selbst bestimmen?
Delphi-Quellcode:
const X: array[] of string = ('1', '2');




Zitat:

Delphi-Quellcode:
var
  a1: array of String;
  a2: TArray<String>;

Array of string definiert an dieser stelle einen neuen Typ und der ist dann mit dem anderen Array nicht zuweisungskompatibel (auch wenn die Typen intern ja eigentlich gleich sind-
Entsprechend dem obrigen Beispiel das, was der Compiler daraus macht:
Delphi-Quellcode:
type
  T1: array of String;
  T1: array of String;
var
  a1: T1;
  a2: T2;
Delphi-Quellcode:
type
  Tx: array of String; // globaler Typ aus TArray<T>
var
  a1: Tx;
  a2: Tx;

Bei den Generics ala TArray<T> werden die gleichgeschriebenen Typen überall auch gleich identisch verwendet, also mit dem selben Typen der ersten Deklaration.



Zitat:

Delphi-Quellcode:
type
  TRec = record
  const
    MyArray: TArray<String> = ['First','Second','Third'];
  end;

Bei Dem dachte ich zuerst an
Delphi-Quellcode:
const
  Rec = record
    MyArray: array[0..2] of string;
  end = (MyArray: ('First','Second','Third'));
:oops:

DieDolly 5. Dez 2019 18:01

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Kann Delphi nicht auch inzwischen bei statischen Arrays die Länge selbst bestimmen?
Nein.

Dennis07 6. Dez 2019 01:37

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1452832)
Interessant dabei ist, daß man den Alias gar nicht verwenden muss...

LOL.

Zitat:

Zitat von DieDolly (Beitrag 1452840)
Zitat:

Kann Delphi nicht auch inzwischen bei statischen Arrays die Länge selbst bestimmen?
Nein.

Streng genommen: Doch, kann es. Das merkst du auch, wenn du versuchst, eine andere Elementanzahl zuzuweisen, als du vorher deklariert hast.

Woran es aber dann scheitert, hat weniger mit der Länge, als mit dem Wertebereich des Schlüsseltypen zu tun, den du verwendest. Delphi kann jeden beliebigen zählbaren Typen als Schlüsseltypen für statische Arrays verwenden. Das muss nicht zwingend ein Zahlenwert weil, ist es nur meistens.
Zur Folge hat dies, dass der Compiler nie genau sagen kann, welchen Wertebereich du für den Schlüssel verwenden willst. Aus kompatibilitätsgründen sind nämlich sowohl negative, als auch lückenhafte Typen sowie Bereichstypen als Schlüssel zulässig. Der Compiler wüsste nie, welchen Bereich er nehmen soll, wenn die Wertemenge von der Gesamtmenge aller Schlüsselmöglichkeiten abweicht.

DieDolly 6. Dez 2019 08:13

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Aus kompatibilitätsgründen
Im Prinzip werden Delphi 10.3-Kunden damit bestraft. Mich interessiert kein älteres Delphi.
Der 10.3 Compiler sollte auch auf 10.3 ausgelegt sein. Abwärtskompatibilität, weg damit. Wer einen älteren Compiler will, soll ein älteres Delphi installieren.

Daniel 6. Dez 2019 08:16

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von DieDolly (Beitrag 1452864)
Abwärtskompatibilität, weg damit.

Wie viele Projekte nennenswerter Größe hast Du zu pflegen? Ich schätze, dass das wenige sein werden.

Uwe Raabe 6. Dez 2019 08:29

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von Daniel (Beitrag 1452865)
Wie viele Projekte nennenswerter Größe hast Du zu pflegen? Ich schätze, dass das wenige sein werden.

:thumb:

DieDolly 6. Dez 2019 08:37

AW: TArray<string> als const im Record deklarieren
 
Das hätte man auch netter formulieren können.
Nur weil man Hobbyprogrammierer ist heißt das nicht, dass man keine großen Projekte zu pflegen hat. Ein Schlag ins Gesicht für alle kleinen Hobbyentwickler direkt vom Administrator des Delphiforums :thumb:

Neutral General 6. Dez 2019 09:33

AW: TArray<string> als const im Record deklarieren
 
Es war nur eine Frage, kein Schlag ins Gesicht. :roll:

Uwe Raabe 6. Dez 2019 09:48

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von DieDolly (Beitrag 1452864)
Abwärtskompatibilität, weg damit. Wer einen älteren Compiler will, soll ein älteres Delphi installieren.

Diese Aussage ist vollkommen realitätsfern! Wenn Delphi nicht so außergewöhnlich abwärtskompatibel wäre, müsste bei einer Umstellung ein enormer Zeit- und Kostenaufwand veranschlagt werden. Der ist auch mit dieser Kompatibilität schon manchmal beträchtlich. Da müssen eine ganze Reihe Entwicklungsumgebungen in realen und virtuellen Maschinen umgestellt werden, alle Build-Rechner brauchen eine neue Delphi-Installation und die Build-Skripte müssen angepasst werden. Während der Umstellung und als Fallback müssen die alten Versionen aber immer noch verfügbar sein. Kommen jetzt noch Code-Änderungen dazu, muss das ganze Projekt auch noch umfassende Tests durchlaufen. Die Kosten für eine solche Umstellung sind schon beträchtlich und übersteigen in der Regel die Update- oder Subscription-Kosten deutlich, von den Gefahren unbemerkter Bugs mal ganz zu schweigen.

DasWolf 6. Dez 2019 09:48

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von DieDolly (Beitrag 1452867)
Das hätte man auch netter formulieren können.
Nur weil man Hobbyprogrammierer ist heißt das nicht, dass man keine großen Projekte zu pflegen hat. Ein Schlag ins Gesicht für alle kleinen Hobbyentwickler direkt vom Administrator des Delphiforums :thumb:

Es ist egal, wer es schreibt. Ob einfache Mitglieder, der Administrator oder Angelo Merte. Es ist auf jeden Fall sachlich und richtig formuliert.

Dennis07 6. Dez 2019 11:11

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von DieDolly (Beitrag 1452864)
Zitat:

Aus kompatibilitätsgründen
Im Prinzip werden Delphi 10.3-Kunden damit bestraft. Mich interessiert kein älteres Delphi.
Der 10.3 Compiler sollte auch auf 10.3 ausgelegt sein. Abwärtskompatibilität, weg damit. Wer einen älteren Compiler will, soll ein älteres Delphi installieren.

Also das ist direkt mehrfach falsch.

Also, erstens, habe ich doch nirgendwo etwas von "Abwärtskompatibilität" gesagt. Weil es nämlich auch nicht stimmt. Statische Arrays funktionieren in Delphi 10.3.3 noch genau wie unter Delphi 1 (zumindest meines Wissens nach).
Was ich meinte, als ich von Kompatibilität sprach, war eher (und ich dachte eigentlich, dass sich das aus dem gesetzten Kontext ergibt) die Kompatibilität zu allen möglichen Schlüsseltypen/-bereichen.

Delphi-Quellcode:
Integer
bzw.
Delphi-Quellcode:
LongInt
bzw.
Delphi-Quellcode:
Int32
ist definiert als ein ganzzahliger, zählbarer Typ mit dem Wertebereich von
Delphi-Quellcode:
Succ(MaxInt) .. MaxInt
. Er wird als Schlüsseltyp für alle dynamischen Arrays, aber auch für die meisten statischen Arrays benutzt. Woher soll der Compiler jetzt aber wissen, welche Schlüssel du für ein statisches Array benutzen möchtest, dessen Elementezahl sich von der Gesamtzahl aller Schlüssel des Wertebereichs unterscheidet?

Das ist schlichtweg nicht möglich. Deshalb musst du immer einen gesamten Wertebereich als Schlüssel angeben, inklusive Ober-und Untergrenze. Das macht den Schlüssel des Arrays kompatibel mit dem entsprechenden Bereichstypen, den es verwendet (beispielsweise ist der Schlüssel eines Arrays mit der Deklaration
Delphi-Quellcode:
array [0..5] of T
ein anonymer Inline-Typ, der einen Teilbereich des numerischen Standardtyps
Delphi-Quellcode:
Integer
abbildet und somit zu allen ganzzahligen Typen kompatibel ist, sofern diese mit Integer kompatibel sind).

Definiert die Untergrenze des Schlüssel-Wertebereichs deshalb ein Offset für die Speicherung der Werte in einem Array?
Nein, der Compiler sorgt dafür, dass die entsprechenden Indizes so umgerechnet werden, dass sie für den Programmierer so dargestellt werden. Tatsächlich aber hat ein statisches Array, dessen Schlüsselbereich bei 256 anfängt, nicht ein 255 lehre Speicherblöcke vorweg.

Was ist der Vorteil?
Vorteile gibt es verschiedene. Es ist zum einen eine Bequemlichkeitsfrage: Ich kann einen Aufzählungstypen als Schlüssel verwenden, ohne mich um dessen Wertebereich kümmern zu müssen. Ich muss nicht einmal einen neuen Unterbereich definieren, sondern kann den Bezeichner des Bereichstypen (zB. ein Enum) direkt als Schlüsseltypen verwenden. Der Compiler kennt dadurch die Ober-und Untergrenze des Arrays und weiß, wie viele Werte es gibt und wo er sie hinpacken muss.

Dann wäre da noch ein praktischer Vorteil: Die Kompatibilität zu aufzählungstypen: Man kann ein
Delphi-Quellcode:
array[0..n-1] of Char
beispielsweise von und/oder zu einem langen String (
Delphi-Quellcode:
AnsiString
,
Delphi-Quellcode:
String
bzw.
Delphi-Quellcode:
WideString
oder
Delphi-Quellcode:
UnicodeString
) oder einem PChar, oder aber einem dynamischen
Delphi-Quellcode:
array of Char
explizit zuweisen (bei String-Literalen genügt sogar eine implizite Zuweisung, da diese automatisch Zieltypisiert werden können).

himitsu 8. Dez 2019 18:17

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Was ist der Vorteil?
Nein, du musst immer die untere und obere Grenze angeben.
Auch bei
Delphi-Quellcode:
array[TIrgendeinEnum] of ...
ist der untere Bereich gegeben, denn der Enum ist nunmal so definiert, dass er bei 0 beginnt.

Aber jupp, bei einem Offset der unteren Grenze, da rechnet der Compiler überall beim Speicherzugriff dieses Offset automatisch ein und lässt so den genutzten Speicher bei "0" beginnen.



Zitat:

Wenn Delphi nicht so außergewöhnlich abwärtskompatibel wäre
Leider kann man das inzwschen vergessen.

Hach, erinnert sich noch jemand, wie die Firma beim Turbo-Delphi noch so stolz zeigte wie cool abwärtskompatibel doch alles sei?

Seit Delphi 2009 geht es stark bergab.
Spätestens mit Einführung von NextGen ist Delphi nichtmal mehr in der selbenn Version kompatibel.
denn vor allem AutoRefCount macht es nahezu unmöglich einen kompatiblen Code zu schreiben, der überall läuft.


Ab Januar läuft auch für mich der Support von allem vor Windows 10 aus (Win7 ist tot, Win8 nutzt keiner freiwillig, aber seit Win8 gibt es zuviele nette neue APIs)
und auch der Support für alte Delphis gab ich schweren Herzens explizit auf. (XE* und alles davor wird nur noch implizit unterstützt ... entweder es läuft, oder pech gehabt)
Die neuen wieder "kostenfreien" Delphis haben mir da die Entscheidung abgenommen, da auch ohne Geld Aktuelleres möglich ist.

Bei 64 Bit, da liegt es nicht an Delphi ... hier hatte Intel den Vogel abgeschossen, dass der Gedanke Integer und Pointer passen sich an, nun nicht mehr stimmt und somit so einige Codes mühevoll angepasst werden mussten.

Dennis07 8. Dez 2019 19:51

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von himitsu (Beitrag 1452982)
Zitat:

Was ist der Vorteil?
Nein, du musst immer die untere und obere Grenze angeben.
Auch bei
Delphi-Quellcode:
array[TIrgendeinEnum] of ...
ist der untere Bereich gegeben, denn der Enum ist nunmal so definiert, dass er bei 0 beginnt.

Wieso denn Nein, wenn du danach überhaupt nicht widersprichst? :-D
Ein Enum ist, genau wie ein ganzzahliger Typ, ein Wertebereich. Und den kannst du entweder vollständig, oder aber teilweise als Schlüssel für ein statisches Array benutzen. Nichts anderes hatte ich versucht zu erklären. Wenn es missverständlich war, bitte ich dies zu entschuldigen.

himitsu 8. Dez 2019 22:08

AW: TArray<string> als const im Record deklarieren
 
Entweder du gibst beide Grenzen rein (
Delphi-Quellcode:
array[b..e] of xyz
),
oder einen Typen, der in sich beide Grenzen enthält (
Delphi-Quellcode:
array[EnumOrOtherOrdinalType] of xyz
),
also im Endefekt gibst du somit immer beide Grenzen rein. :zwinker:

Sowas wie im C++ und anderen Sprachen geht im Delphi nicht, also nur die Anzahl und implizit beginnt es bei 0:
Delphi-Quellcode:
array[13] of xyz
für
Delphi-Quellcode:
array[0..Anzahl-1] of xyz

DieDolly 9. Dez 2019 09:17

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Sowas wie im C++ und anderen Sprachen geht im Delphi nicht, also nur die Anzahl und implizit beginnt es bei 0: array[13] of xyz für array[0..Anzahl-1] of xyz
Wäre eventuell nicht verkehrt, denn dann gäbe es weniger Leute (in Schulen), die ihre Zählung bei 1 statt 0 anfangen.

freimatz 9. Dez 2019 12:15

AW: TArray<string> als const im Record deklarieren
 
Und was so daran besser sein? Wenn ich Dinge zähle fange ich immer bei 1 an.
Habe gerade bei uns nach "[1.." gesucht - sechs Treffer. Es sind alles "[1..3]". Keinen finde ich verkehrt.
Aber wir schweifen ab.

Dennis07 9. Dez 2019 17:55

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von DieDolly (Beitrag 1453007)
Zitat:

Sowas wie im C++ und anderen Sprachen geht im Delphi nicht, also nur die Anzahl und implizit beginnt es bei 0: array[13] of xyz für array[0..Anzahl-1] of xyz
Wäre eventuell nicht verkehrt, denn dann gäbe es weniger Leute (in Schulen), die ihre Zählung bei 1 statt 0 anfangen.

Jo, wäre vielleicht in vielerlei hinsicht nicht so dumm. Aber da jetzt noch ein
Delphi-Quellcode:
0..
an den Anfang zu schreiben ist denke ich eine zumutbare Anforderung an den Programmierer. Aber du hast natürlich Recht, semantischer Zucker wäre so etwas. Es würde einige Deklarationen um einiges verkürzen.
Damit der Compiler aber immer noch weiß, dass das nicht der gesamte Wertebereich sondern nur die obere Grenze ist, sollte die Deklaration vielleicht nicht genau so aussehen.

Aber mal ehrlich: Kommen wird das sicher ohnehin nicht, also warum da jetzt Gedanken hin verschwenden. Es gibt statische Arrays, die alles unterstützen, was man sich wünschen könnte und was der Compiler gleichzeitig noch hergibt. Und es gibt dynamische Arrays, die immer bei 0 beginnen und alles andere unterstützen, was statische nicht können.

himitsu 9. Dez 2019 18:27

AW: TArray<string> als const im Record deklarieren
 
Nein, wird nicht kommen, denn der Wunsch wurde schon zu oft in den letzten Jahren gestellt, aber passiert ist nie was.

Das poplige FreePascal (Lazarus) kann sowas seit ewig, da kann Delphi das doch nicht nachmachen.

Stevie 10. Dez 2019 10:08

AW: TArray<string> als const im Record deklarieren
 
Zitat:

Zitat von himitsu (Beitrag 1453098)
Das poplige FreePascal (Lazarus) kann sowas seit ewig, da kann Delphi das doch nicht nachmachen.

Also in FPC 3.0.4 kompiliert das nicht:
Delphi-Quellcode:
type x = array[13] of Integer;

himitsu 15. Dez 2019 14:09

AW: TArray<string> als const im Record deklarieren
 
Ist schon wieder paar Jahre her, das ich FPC benutzt hatte.
Aber ich bin mir ganz sicher damals ein paar Codes gesehen zu haben, wo sowas ging.

Aber vielleicht war da auch irgendeine Erweiterung, Makro oder so beteiligt?
Schade, dass Borland/Codegear die Möglichkeit für einen Precompiler zerstört haben. (echte Makros wären schon was)


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:48 Uhr.

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