2014-04-29 10 views
13

Ich habe ziemlich viele Variablen wieIst es sicher, mit tarray Array von XXX zu ersetzen <XXX>

erklärt
var 
    Something: array of XXX; 
begin 
    SetLength(Something, 10); 
    try 
    ... 
    finally 
    SetLength(Something, 0); 
    end; 
end; 

Inwieweit sicher ist, sie ersetzt zu haben:

var 
    Something: TArray<XXX>; 
begin 
    SetLength(Something, 10); 
    try 
    ... 
    finally 
    SetLength(Something, 0); 
    end; 
end; 
+4

Nur eine Anmerkung: Sie müssen 'try' /' finally' nicht verwenden, um den Speicher eines dynamischen Array-Typs freizugeben. Sie sind refcounted Typen, und der Speicher wird automatisch freigegeben, sobald 'Something' den Gültigkeitsbereich verlässt, es sei denn, sie werden immer noch von einer anderen Variablen referenziert. In jedem Fall verhält es sich genauso wie Ihre 'SetLength' zu einer Länge von Null. – hvd

Antwort

12

Wie bereits beantwortet, TArray<XXX> ist genau wie alle anderen benutzerdefinierten Typ als array of XXX definiert. In der Tat ist TArray<XXX> ein benutzerdefinierter Typ definiert als array of XXX.

Das heißt, eine benutzerdefinierte Typ wie array of XXX definiert ist nicht entspricht array of XXX im Rahmen eines Verfahrens oder Funktionsparameter. In procedure Foo(x: array of Integer), x ist ein open array parameter, der jede Art von Integer-Array akzeptieren kann. Im Gegensatz dazu nimmt procedure Foo(x: TArray<Integer>) nur einen tatsächlichen TArray<Integer> Typ. Sie können den Unterschied sehen, wenn Sie versuchen, ein Array fester Größe zu übergeben, aber auch, wenn Sie versuchen, eine (ein anderer Typ, auch als array of Integer definiert) zu übergeben.

Also, für Variablen, sicher, wenn Sie array of XXX haben, ändern Sie es auf TArray<XXX> alles was Sie wollen. Stellen Sie nur sicher, dass Sie keine globale Suche durchführen und ersetzen.

+0

+1 für die Unterscheidung zwischen Variablen und Methodenargumenten. Aber selbst für die Methodenargumente können Sie sich nicht für das eine oder das andere entscheiden, wenn Sie den Code nicht kennen und analysieren. Während Sie ein 'TArray ' an ein 'Array von XXX' übergeben können, können Sie kein' Array von XXX' an ein 'TArray ' übergeben. In manchen Fällen können Sie also das Argument 'TArray ' verwenden und in anderen Fällen möchten Sie es als' Array von XXX' behalten. –

+0

Ich stimme dem ersten Absatz nicht zu. Diese Typen sind nicht identisch. Sie sind unterschiedliche Typen und nicht zuweisungskompatibel. –

+0

@DavidHeffernan Im ersten Absatz gab es nur ein kleines Problem mit meiner Wortwahl. Der zweite Absatz hatte einen größeren Fehler. Bearbeitete meine Antwort, um das zu adressieren. – hvd

5

Es ist absolut sicher, um dies zu tun. Der Compiler wird identische Ausgabe produzieren.

Ich persönlich würde, wenn alle anderen Dinge gleich sind, empfehlen, dies zu tun. Die Verwendung des generischen Arrays TArray<T> gibt Ihnen viel mehr Flexibilität und bessere Typkompatibilität.

Natürlich können diese Vorteile nur mit realistischerem Code gesehen werden, der etwas Arbeit leistet. Am häufigsten sehen Sie Vorteile bei der Verwendung von generischen Containern. Sie können jedoch auch Vorteile sehen, wenn Sie versuchen, Code mit mehreren verschiedenen Bibliotheken zu erstellen.

Die Verwendung generischer Arrays ermöglicht eine einfache Typenkompatibilität. Bevor generic-Arrays würden Sie ein Array-Typ wie folgt definieren:

TIntArray = array of Integer; 

Wenn zwei Bibliotheken tun dies dann Sie inkompatible Typen haben. Wenn die Bibliotheken zustimmen, generische Arrays zu verwenden, wird Kompatibilität gegeben sein.

Um dies zu sehen deutlicher, dieses Fragment betrachten:

type 
    TIntArray1 = array of Integer; 
    TIntArray2 = array of Integer; 
.... 
var 
    arr1: TIntArray1; 
    arr2: TIntArray2; 
.... 
arr1 := arr2; 

Diese Zuordnung ist nicht gültig und nicht mit einem Typ Mismatch-Compiler-Fehler. Dies ist in der Pascal-Sprache durchaus zu erwarten. Es ist schließlich stark typisiert und das sind unterschiedliche Typen. Auch wenn sie identisch implementiert sind.

Auf der anderen Seite:

var 
    arr1: TArray<Integer>; 
    arr2: TArray<Integer>; 
.... 
arr1 := arr2; 

gültig ist und nicht kompiliert. Die documentation for generic type compatibility sagt:

Zwei instanzierte Generika Zuordnung vereinbar angesehen werden, wenn die Basistypen identisch sind (oder sind Aliase in einen gemeinsamen Typ) und die Typargumente sind identisch.

+1

Der Compiler wird identische Ausgabe erzeugen ... es sei denn, Sie interessieren sich für RTTI, in diesem Fall kann 'TArray ' leider fehlschlagen. (Es sei denn, dies wurde in neueren Versionen behoben?) –

+2

@MasonWheeler, genau! F.i. Das von Datasnap verwendete JSON-Marshalling kann perfekt mit einem Feldtyp arbeiten, der als 'Array von T' deklariert ist, aber für' TArray ' fehlschlägt. Wie so oft ist die Antwort: Es kommt darauf an. –

+0

Sicherlich wurde das behoben. 'TArray ' ist grundlegend. –