Deklaration von Inline-Variablen

Aus RAD Studio
Wechseln zu: Navigation, Suche

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).

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’