Deklaration von Inline-Variablen
In der Version 10.3 lässt die Delphi-Sprache größere Flexibilität bei der Deklaration lokaler Variablen zu. Entsprechend den Pascal-Sprachregeln mussten bis jetzt alle Variablendeklarationen in einem "var"-Block vor dem Beginn einer Funktion, Prozedur oder Methode erfolgen:
procedure Test;
var
I: Integer;
begin
I := 22;
ShowMessage (I.ToString);
end;
Mit der neuen Syntax für die Deklaration von Inline-Variablen können Sie die Variable direkt in einem Codeblock deklarieren (und auch wie üblich mehrere Symbole verwenden):
procedure Test;
begin
var I: Integer;
I := 22;
ShowMessage (I.ToString);
end;
procedure Test2;
begin
var I, K: Integer;
I := 22;
K := I + 10;
ShowMessage (K.ToString);
end;
Dies scheint nur ein kleiner Unterschied zu sein, aber es gibt mehrere Nebenwirkungen dieser Änderung. Erstens: Die Deklaration und Initialisierung kann in einer Anweisung vorgenommen werden. Zweitens: Sie können bei Bedarf Variablen in komplexen Codeblöcken mit begrenztem Gültigkeitsbereich deklarieren (da die Variable nur ab der Position ihrer Deklaration sichtbar ist, und sie nicht deklariert, aber nicht initialisiert in anderen Codeteilen vorhanden sein muss).
Inhaltsverzeichnis
Gültigkeitsbereich von Inline-Variablen
Ein dritter Nebeneffekt ist, dass die Deklaration auch innerhalb eines begin-end-Blocks der zweiten Ebene zulässig ist und der Gültigkeitsbereich auf diesen Block beschränkt ist.
procedure Test; // declaration and initialization in a single statement
begin
var I: Integer := 22;
ShowMessage (I.ToString);
end;
procedure Test1; // multiple inline declarations (symbols declared when used)
begin
var I: Integer := 22;
var J: Integer;
J := 22 + I;
var K: Integer := I + J;
ShowMessage (K.ToString);
end;
procedure Test2; // scope limited to local block
begin
var I: Integer := 22;
if I > 10 then
begin
var J: Integer := 3;
ShowMessage (J.ToString);
end
else
begin
var K: Integer := 3;
ShowMessage (J.ToString); // COMPILER ERROR: “Undeclared identifier: ‘J’”
end;
end;
Wie Sie dem letzten Codefragment oben entnehmen können, ist eine in einem begin-end-Block deklarierte Variable nur in diesem Block sichtbar und nicht nachdem der Block beendet wurde. Am Ende der if-Anweisungen sind J und K nicht mehr sichtbar.
Der Effekt bezieht sich nicht nur auf die Sichtbarkeit. Eine verwaltete Variable, wie eine Interface-Referenz oder ein Record, wird am Ende des Blocks ordnungsgemäß bereinigt, nicht erst am Ende der Prozedur oder Methode:
procedure Test99;
begin
// some code
if (something) then
begin
var Intf: IInterface = GetInterface; // Intf.AddRef
var MRec: TManagedRecord = GetMRecValue; // MRec.Create + MRec.Assign
UseIntf(Intf);
UseMRec(MRec);
end; // Intf.Release and MRec.Destroy are implicitly called at end of scope
// more code
end; // no additional cleanup
Typableitung für Inline-Variablen
Außerdem kann der Compiler jetzt in verschiedenen Situationen an der Position ihrer Deklaration den Typ einer Variable vom Typ des zugewiesenen Werts ableiten.
procedure Test;
begin
var I := 22;
ShowMessage (I.ToString);
end;
Der Typ des R-Wertausdrucks (das ist das, was nach dem := steht) wird analysiert, um den Typ der Variable zu ermitteln. Einige Datentypen werden auf größere Typen "erweitert", wie in dem oben dargestellten Beispiel, in dem der numerische Wert 22 (ein ShortInt) auf Integer erweitert wird. Als allgemeine Regel gilt: Wenn der Typ des Ausdrucks auf der rechten Seite ein integraler Typ und kleiner als 32 Bit ist, dann wird die Variable als 32-Bit-Integer deklariert. Sie können einen expliziten Typ verwenden, wenn Sie einen bestimmten, kleineren, numerischen Typ haben möchten.
Beachten Sie auch, dass nur ein einziger Bezeichner ohne Wertetyp deklariert werden kann (abweichend von allgemeinen Variablendeklarationen und Inline-Deklarationen).
Diese Funktion erspart Ihnen ein paar Tastenanschläge bei einem Integer oder String, aber die Typableitung von Variablen bei komplexen Typen, wie z. B. Instanzen von generischen Typen, wird erheblich einfacher. Im folgenden Codefragment sind die abgeleiteten Typen "TDictionary<string, Integer>" für die Variable MyDictionary und "TPair<string, Integer>" für die Variable APair.
procedure NewTest;
begin
var MyDictionary := TDictionary<string, Integer>.Create;
MyDictionary.Add ('one', 1);
var APair := MyDictionary.ExtractPair('one');
ShowMessage (APair.Value.ToString)
end;
Inline-Konstanten
Neben Variablen können Sie jetzt auch Konstantenwerte inline deklarieren. Dies kann sowohl für typisierte Konstanten als auch für nicht typisierte Konstanten angewendet werden. Im letzteren Fall wird der Typ abgeleitet (ein Feature, das seit langem für Konstanten verfügbar ist). Hier ist ein einfaches Beispiel:
const M: Integer = (L + H) div 2; // single identifier, with type specifier
const M = (L + H) div 2; // single identifier, without type specifier
For-Schleifen mit Variablendeklaration
Ein spezieller Fall, in dem Sie die Vorteile von Inline-Variablendeklarationen nutzen können, sind Schleifenanweisungen, einschließlich for-to-Schleifen und for-in-Schleifen.
for var I: Integer := 1 to 10 do ...
for var Item: TItemType in Collection do...
Sie können den Code durch Typableitung weiter vereinfachen:
for var I := 1 to 10 do ...
for var Item in Collection do ...
Im folgenden Code ist eine Variable mit begrenztem Gültigkeitsbereich besonders nützlich: Durch Verwendung der Variable 'I' außerhalb der Schleife wird ein Compiler-Fehler verursacht (früher wurde meistens nur eine Warnung ausgegeben):
procedure ForTest;
begin
var total := 0;
for var I: Integer := 1 to 10 do
Inc (Total, I);
ShowMessage (total.ToString);
ShowMessage (I.ToString); // compiler error: Undeclared Identifier ‘I’