суббота, 19 марта 2011 г.

Инструкции

Перевод из справочной системы Delphi

Инструкции определяют алгоритмические действия внутри программы. Простые инструкции, такие как присваивание и вызовы процедур могут быть объединены в циклы, условные инструкции и другие структуры.


Составные инструкции внутри блоков и секциях initialization и finalization разделяются точками с запятой (;).


Простые инструкции

Простые инструкции не содержат в себе других инструкций. Простые инструкции – это присваивание, вызовы процедур и функций, переходы goto.


Инструкции присваивания

Инструкции присваивания имеет следующую форму:

Variable := expression

Где Variable – это ссылка на переменную, включая переменные, переменные с преобразованием типа, указатели или компоненты переменных структурированного типа.

Expression – любое выражение совместимое по присваиванию (внутри блока функции, переменная может быть заменена именем этой функции).

Символ ':=' иногда называют оператором присваивания. Оператор присваивания заменяет текущее значение переменной значением expression. Например:

I := 3;

Присваивает значение 3 переменной I. Переменная, указываемая в левой части выражения может присутствовать и в правой части. Например:

I := I + 1;

Увеличивает значение I. Кроме того, инструкции присваивания могут использоваться следующим образом:

X := Y + Z;
Done := (I >= 1) and (I < 100);
Hue1 := [Blue, Succ(C)];
I := Sqr(J) - I  * K;
Shortint(MyChar) := 122;
TByteRec(W).Hi := 0;
MyString[I] := 'A';
SomeArray[I + 1] := P^;
TMyObject.SomeProperty := True;

Вызовы процедур и функций

Вызов процедуры состоит из имени процедуры (с указанием спецификатора или без такового), за которым следует список параметров (если требуется). Например:

PrintHeading;
Transpose(A, N, M);
Find(Smith, William);
Writeln('Hello world!');
DoSomething();
Unit1.SomeProcedure;
TMyObject.SomeMethod(X,Y);

При включении расширенного синтаксиса ({$X+}), вызовы функций могут обрабатываться так же как вызовы процедур:

MyFunction(X);

Когда вы вызываете функции таким образом, возвращаемые ими значения отбрасываются.


Инструкция Goto

Инструкция имеет форму:

goto label

и переносит выполнение программы на инструкцию, помеченную соответствующей меткой. Для установки такой отметки, необходимо сначала объявить метку. Затем вы должны предварить его меткой и двоеточием (:).

label: statement
Метка объявляется следующим образом:
label label;
Вы можете объявить сразу несколько меток:
label label1, ..., labeln;

Метка может быть любым допустимым идентификатором или числом от 0 до 9999. Объявление метки, помеченная инструкция и инструкция goto должны принадлежать одному блоку. То есть невозможно перейти в (или из) процедуру или функцию. Не помечайте одной меткой более одной инструкции. Например:

label StartHere;
    ...
StartHere: Beep;
goto StartHere;
Создает бесконечный цикл, который вызывает процедуру Beep.

Кроме того, нет возможности перехода в (из) блоки try - finally или try -except. Инструкция goto часто не рекомендуется в структурном программировании. Однако, она иногда используется как способ выхода из вложенных циклов. Например:

procedure FindFirstAnswer;
  var X, Y, Z, Count: Integer;
label FoundAnAnswer;
begin
  Count := SomeConstant;
  for X := 1 to Count do
    for Y := 1 to Count do
      for Z := 1 to Count do
        if ... { some condition holds on X, Y, and Z } then
          goto FoundAnAnswer;

  ... { Code to execute if no answer is found }
  Exit;

  FoundAnAnswer:
    ... { Code to execute when an answer is found }
end;

Обратите внимание, что мы используем goto для выхода из вложенного цикла. Никогда не используйте эту инструкцию для входа в цикл или структурированную инструкцию, поскольку это может привести к непредсказуемым поcледствиям.


Структурированные инструкции

Структурированные инструкции состоят из других инструкции. Применяйте структурированные инструкции, когда хотите выполнять прочие инструкции последовательно, условно или циклически.

Составные инструкции или инструкции with просто исполняют последовательность составных инструкции.

Условные инструкции if или case выполняют не более одной из своих инструкций в зависимости от указанного критерия.

Инструкции цикла repeat, while, и for выполняют последовательность своих вложенных инструкций циклически.

Особая группа инструкций, включающая конструкции raise, try...except и try...finally создает и обрабатывает исключительные ситуации.


Составные инструкции

Составные инструкции – это последовательность других инструкции (простых или составных), выполняемых в последовательности, в которой они следуют в программном коде. Составные инструкции обрамляются зарезервированными словами begin и end, а входящие в их состав простые инструкции разделяются точками с запятой (;). Например:

begin
   Z := X;
   X := Y;
   X := Y;
end;

Последняя точка с запятой перед end необязательна. То есть этот пример может быть записан и так:

begin
   Z := X;
   X := Y;
   Y := Z
end;

Составные инструкции необходимы в случаях, когда синтаксис Delphi требует одной инструкции. Кроме блоков в программах, функциях или процедурах, их можно встретить внутри других составных инструкций (условных или инструкциях циклов). Например:

begin
  I := SomeConstant;
  while I > 0 do
  begin
    ...
    I := I - 1;
  end;
end;

Вы можете написать составную инструкцию, которая содержит единственный включенную инструкцию. Как и скобки в сложных выражениях begin и end иногда служат для того, чтобы упростить программный код и улучшить его читаемость. Вы также можете использовать пустые составные инструкции, которые не делают ничего:

begin
end;

Инструкция With

Инструкция with это стенографический прием для обращения к полям записей или полям, свойствам или методам объектов. Синтаксис инструкции with:

with obj do 
  statement
или:
with obj1, ..., objn do 
  statement

где obj это выражение, ссылающееся на объект, экземпляр объекта, экземпляр класса, интерфейса или экземпляр типа класса (метакласса).

statement - это любая простая или структурированная инструкция. Внутри statement вы можете обращаться к полям, свойствам и методам obj используя только их идентификаторы без спецификатора. Например:

type
  TDate = record
    Day: Integer;
    Month: Integer;
    Year: Integer;
  end;

var
  OrderDate: TDate;
//можно записать следующую инструкцию with: 
with OrderDate do
  if Month = 12 then
    begin
      Month := 1;
      Year := Year + 1;
  end
  else
    Month := Month + 1;
// без инструкции with этот пример будет выглядеть: 
if OrderDate.Month = 12 then
begin
  OrderDate.Month := 1;
  OrderDate.Year := OrderDate.Year + 1;
end
else
  OrderDate.Month := OrderDate.Month + 1;

Если интерпретация obj включает индексированние массива или переход по указателю, эти действия выполняются однократно перед выполнением инструкции. Это делает инструкцию with эффективной и экономичной. Это также обозначает, что присвоение значений переменных внутри инструкции не могут действовать на интерпретацию obj во время выполнения текущей инструкции with.

Каждое обращение к переменной или имени метода интерпретируется, если это возможно, как обращение к элементу указанного объекта или записи. Если существует другая переменная или метод с тем же именем, к которой вам необходимо получить доступ внутри инструкции with вам необходимо указать для нее спецификатор. Например:

with OrderDate do
  begin
    Year := Unit1.Year;
     ...
  end;

Когда в инструкции with, указывается несколько объектов или записей, вся конструкция интерпретируется как последовательность вложенных инструкций with. То есть:

with obj1, obj2, ..., objn do 
  statement
эквивалентно:
with obj1 do
  with obj2 do
    ...
    with objn do
      statement

В этом случае, каждое обращение к переменной или имени метода внутри инструкции интерпретируется, если возможно, как элемент objn, в противном случае, как элемент objn1; и так далее. То же самое правило применяется к интерпретации objs самих по себе. То есть, если, например, objn – это одновременно элемент obj1 и obj2, он интерпретируется как obj2.objn.

Поскольку для управления в инструкции with необходима переменная или поля, использование его для работы со свойствами, иногда может быть непростым. Инструкция with ожидает, что переменные, с которыми она обращается будут доступны по ссылке.

Основные моменты, которые необходимо учесть при использовании with:
  • Вы можете использовать with только для чтения значений свойств, помеченных только для чтения. Попытка изменить значение поля в записи или объекте, к которым обеспечивает доступ свойство, приводит к ошибке компиляции.
  • Даже если свойство позволяет производить запись в поле, вы все равно не можете использовать инструкцию with для изменения значения этого поля.

Следующий пример иллюстрирует проблему применения инструкции with на свойствах, помеченных только для чтения и обеспечивающих доступ к записям. Предположим, у вас есть следующий класс:

TShape = class
 private
   FCenter: TPoint;
 public
   property Center: TPoint read FCenter;
 end;
где TPoint это запись, которая объявлена следующим образом:
TPoint = record
   X, Y: Integer;
 end;

В общем случае свойство Center помечено как "только для чтения" и не позволяет изменять значение поля FCenter. В этом случае использование инструкции with приведет к ошибке компиляции. Center – это не переменная, и вы не можете ссылаться на нее:

with Shape.Center do
 begin
   X := 100;
   Y := 100;
 end;

Сложность также возникает при использовании with для свойств, разрешающих запись. Мы изменили объявление оригинального класса TShape, что бы разрешить запись в поле FCenter:

TShape = class
 private
   FCenter: TPoint;
 public
   property Center: TPoint read FCenter write FCenter;
 end;

Ошибка компиляции возникает даже в том случае, когда свойство Center разрешает запись. Для решения этой проблемы необходимо изменить программный код:

with Shape.Center do
 begin
   X := 100;
   Y := 100;
 end;
следующим образом:
{ копируем значение Center в локальную переменную}
 TempPoint := Shape.Center;

 with TempPoint do
 begin
   X := 100;
   Y := 100;
 end;

 { восстанавливаем значение}
 Shape.Center := TempPoint;

Инструкции If

Существует две формы инструкции if: if...then и if...then...else.

синтаксис инструкции if...then:
if expression then 
  statement

где expression возвращает значение типа Boolean. Если expression возвращает значение True, выполняется инструкция statement. В противном случае этого не происходит. Пример:

if J <> 0 then Result := I / J;
Синтаксис инструкции if...then...else:
if expression then 
  statement1 
else 
  statement2

где expression возвращает значение типа Boolean. Если expression возвращает значение True, выполняется statement1, в противном случае, выполняется statement2. Например:

if J = 0 then
   Exit
else
   Result := I / J;

Разделы then и else содержат по одной инструкции, которые могут быть структурированными. Например:

if J <> o then
begin
  Result := I / J;
  Count := Count + 1;
end
else if Count = Last then
  Done := True
else
  Exit;

Точка с запятой (;)между разделом then и ключевым словом else никогда не ставится. Вы можете поставить точку с запятой (;) после инструкции if , чтобы отделить ее от следующей инструкции в блоке, но разделы then и else требуют, чтобы между ними был только разделитель в виде пробела или символа возврата каретки. Вставка точки с запятой (;) перед else (в инструкции if) это распространенная ошибка при программировании.

Особые сложности возникают при соединении двух вложенных инструкций if. Это происходит потому, что одни инструкции if имеют раздел else, а другие – нет. При этом синтаксис обоих инструкций одинаков. В последовательности вложенных условных инструкций, где количество разделов else меньше, чем количество инструкций if, может быть непонятно, какой раздел else относится к какой инструкции if. Рассмотрим инструкцию вида:

if expression1 then 
  if expression2 then 
    statement1 
else 
  statement2;
Оказывается, есть два способа разбора этого примера:
if expression1 then 
  [if expression2 then 
    statement1 
  else 
    statement2];
if expression1 then 
  [if expression2 then 
     statement1 ] 
else 
  statement2;

Компилятор, однако всегда разбирает такие случаи первым способом. То есть, в реальном программном коде инструкция:

if ... { expression1} then
  if ... {expression2} then
    ... {statement1}
  else
    ... {statement2}
эквивалентна:
if ... {expression1} then
  begin
    if ... {expression2} then
      ... {statement1}
    else
      ... {statement2}
end;

Правило такое: вложенные условные инструкции разбираются, начиная с последней вложенной инструкции, при этом каждый раздел else счязывается с ближайшей слева инструкцией if. Для того, чтобы заставить компилятор прочесть наш пример вторым способом, вам нужно записать его явно следующим образом:

if ... {expression1} then
  begin
   if ... {expression2} then
     ... {statement1}
   end
end
else
   ... {statement2};

Инструкции Case

Инструкции case может предоставить более удобную для чтения альтернативу инструкциям if с глубокой вложенностью. Инструкция case имеет вид:

case selectorExpression of
  caseList1: statement1;
   ...
  caseListn: statementn;
end

где selectorExpression это любое выражение порядкового типа, меньшее, чем 32 бита (строковые типы и порядковые типы с размером более 32 бит не могут быть использованы). Каждый caseList может быть:

  • числом, объявленной константой или выражением, которое компилятор может вычислить без запуска программы. Это может быть порядковый тип, совместимый с selectorExpression. Так 7, True, 4 + 5 * 3, 'A', и Integer('A') могут быть использованы как caseLists, но переменные и большая часть функций не могут. (исключение составляют некоторые встроенные функции вроде Hi и Lo.)
  • Подмножеством, имеющим форму First..Last, где First и Last удовлетворяют указанным выше критериям и First is меньше, либо равно Last.
  • Списком, имеющим форму item1, ..., itemn, где каждый item удовлетворяет вышеуказанным критериям.

Каждое значение представленное caseList должно быть уникальным внутри инструкции case; подмножества и списки не могут пересекаться.

Инструкции case может иметь завершающий раздел else:
case selectorExpression of
  caseList1: statement1;
   ...
  caselistn: statementn;
else
  statements;
end

где statements – это разделенные точками с запятой (;) последовательности инструкций. При выполнении инструкции case, по крайней мере, одна из инструкций statement1 ... statementn выполняется. Какой бы caseList не имел равное значение, selectorExpression определяет инструкцию, которая должна быть выполнена. Если ни один из caseLists не имеет значения, равного selectorExpression, выполняется инструкция из раздела else (если таковой присутствует).

Инструкция case
case I of
  1..5: Caption := 'Low';
  6..9: Caption := 'High';
  0, 10..99: Caption := 'Out of range';
else
  Caption := ;
end 
эквивалентна вложенным условиям:
if I in [1..5] then
  Caption := 'Low';
else if I in [6..10] then
  Caption := 'High';
  else if (I = 0) or (I in [10..99]) then
    Caption := 'Out of range'
    else
      Caption := ;
Другие примеры использования инструкции case
case MyColor of
  Red: X := 1;
  Green: X := 2;
  Blue: X = 3;
  Yellow, Orange, Black: X := 0;
end;

case Selection of
  Done: Form1.Close;
  Compute: calculateTotal(UnitCost, Quantity);
else
  Beep;
end;

Циклы

Циклы позволяют вам повторно выполнять последовательность инструкций, используя контрольное условие или переменную для того, чтобы определять, должно ли выполнение прекратиться. Delphi имеет три вида циклов: repeat, while и for.

Вы можете использовать стандартные процедуры Break и Continue для контроля выполнения инструкций repeat, while и for. Процедура Break прерывает цикл в том месте, где она встречается, а процедура Continue начинает новую итерацию выполнения последовательности вложенных в цикл инструкций.


Инструкция Repeat
Синтаксис инструкции repeat:
repeat 
  statement1; 
  ...; 
  statementn; 
until expression

где expression – это выражение, возвращающее значение типа Boolean. (Последняя точка с запятой (;) перед until необязательна.) Инструкция repeat выполняет последовательность инструкций циклически, вычисляя значение expression после каждой итерации. Когда expression возвращает True, цикл прерывается. Последовательность инструкций выполняется по крайней мере однократно поскольку expression не вычисляется перед первой итерацией. Примеры инструкции repeat:

repeat
  K := I mod J;
  I := J;
  J := K;
until J = 0;

repeat
  Write('Enter a value (0..9): ');
  Readln(I);
until (I >= 0) and (I <= 9);

Инструкция While

Инструкция while схожа с инструкцией repeat, за исключением того, что контрольное условие вычисляется перед первой итерацией. То есть, если контрольное условие возвращает значение false последовательность инструкций не будет выполнена ни разу.

Синтаксис инструкции while:
while expression do 
  statement

где expression – это выражение, возвращающее значение типа Boolean, а statement может быть составной инструкцией. Инструкция while циклически выполняет последовательность инструкций statement, проверяя значение expression перед каждой итерацией. До тех пор, пока expression возвращает значение True, выполнение продолжается.

Пример инструкции while:
while Data[I] <> X do I := I + 1;

while I > 0 do
begin
  if Odd(I) then Z := Z * X;
  I := I p 2;
  X := Sqr(X);
end;

while not Eof(InputFile) do
begin
  Readln(InputFile, Line);
  Process(Line);
end; 

Инструкция For

Инструкция for, в отличие от repeat и while, требует явно указать количество итераций. Синтаксис инструкции for:

for counter := initialValue to finalValue do 
   statement
или:
for counter := initialValue downto finalValue do 
   statement
где:

counter – это локальная переменная (объявленная внутри блока, содержащего инструкцию for) порядкового типа без каких-либо спецификаторов.

initialValue и finalValue – это выражения, совместимые по присваиванию с counter.

statement - это простая или составная инструкция, которая не может изменять значение counter.

Инструкция for присваивает initialValue переменной counter, затем циклически выполняет statement, увеличивая или уменьшая counter после каждой итерации. (Синтаксис for...to увеличивает counter, а for...downto уменьшает.) Когда counter возвращает значение, равное finalValue, statement выполняется последний раз и цикл for прерывается. Другими словами statement выполняется однократно для каждого значения внутри диапазона между initialValue и finalValue. Если initialValue равно finalValue, statement выполняется однократно. Если initialValue больше finalValue в цикле for...to, или меньше чем finalValue в цикле for...downto, statement не выполняется ни разу. После прерывания цикла for (если прерывание не было вызвано процедурами Break илт Exit), значение counter становится неопределенным.

Предупреждение: Итератор counter не может быть изменен внутри цикла присвоением значения или передачей параметра по ссылке в процедуру. Нарушение этого правила приводит к выводу предупреждения при компиляции.

Для целей обеспечения контроля выполнения инструкций внутри цикла выражения initialValue и finalValue вычисляются только однократно перед началом выполнениея цикла. То есть инструкция for...to почти всегда похожа (не полностью) на конструкцию while:

begin
  counter := initialValue;
  while counter <= finalValue do
  begin
    ... {statement};
    counter := Succ(counter);
  end;
end

Различие между этой конструкцией и инструкцией for...to состоит в том, что цикл while повторно вычисляет finalValue перед каждой итерацией. Это может привести к значительному снижению скорости выполнения, в том случае, когда finalValue представляет собой сложное для вычисления выражение. Кроме того, это означает, что изменения значения finalValue внутри statement могут влиять на выполнение цикла.

Примеры
for I := 2 to 63 do
  if Data[I] > Max then
    Max := Data[I];

for I := ListBox1.Items.Count - 1 downto 0 do
  ListBox1.Items[I] := UpperCase(ListBox1.Items[I]);

for I := 1 to 10 do
  for J := 1 to 10 do
  begin
    X := 0;
    for K := 1 to 10 do
      X := X + Mat1[I,K] * Mat2[K,J];
    Mat[I,J] := X;
   end;

for C := Red to Blue do Check(C);

Итерации по элементам контейнеров при помощи инструкции For

Delphi поддерживает итерации типа для-элемента-в-наборе для контейнеров. Компилятором распознается следующие виды итераций по контейнерам:

  • for Element in ArrayExpr do Stmt;
  • for Element in StringExpr do Stmt;
  • for Element in SetExpr do Stmt;
  • for Element in CollectionExpr do Stmt;
  • for Element in Record do Stmt;

Тип итератора Element должен совпадать по типу с типом элементов контейнера. При каждой итерации цикла в итератор помещается значение элемента набора. Так же как и в обычном цикле for, итератор должен быть объявлен внутри блока, содержащего инструкцию цикла for.

Предупреждение: Итератор не может быть изменен внутри цикла присвоением значения или передачей параметра по ссылке в процедуру. Нарушение этого правила приводит к выводу предупреждения при компиляции.

В выражениях, возвращающих значения типа массив, тип массива может быть вектором или многоразмерным, фиксированной или нефиксированной длины (динамический массив). Массив проходится в порядке возрастания, начиная с нижней границы массива и заканчивая величиной, равной размеру массива минус один. Следующий программный код показывает примеры прохождения одномерного, многомерного и динамического массива:

type
  TIntArray        = array[0..9] of Integer;
  TGenericIntArray = array of Integer;

var
  IArray1: array[0..9] of Integer   = 
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  IArray2: array[1..10] of Integer  = 
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  IArray3: array[1..2] of TIntArray = 
    ((11, 12, 13, 14, 15, 16, 17, 18, 19, 20),
     (21, 22, 23, 24, 25, 26, 27, 28, 29, 30));
  MultiDimTemp: TIntArray;
  DynArray: TGenericIntArray;

  I: Integer;

begin
  for I in IArray1 do
  begin
    { Do something with I... }
  end;

  { Indexing begins at lower array bound of 1. }
  for I in IArray2 do
  begin
    { Do something with I... }
  end;

  { Iterating a multidimensional array }
  for MultiDimTemp in IArray3 do   // Indexing from 1..2
    for I in MultiDimTemp do       // Indexing from 0..9
    begin
      { Do something with I... }
    end;

  { Iterating over a dynamic array }
  DynArray := TGenericIntArray.Create(1, 2, 3, 4);

  for I in DynArray do
  begin
    { Do something with I... }
  end;
end. 
Следующий пример показывает прохождения по строковому выражению:
var
  C: Char;
  S1, S2: String;
  Counter: Integer;

  OS1, OS2: ShortString;
  AC: AnsiChar;

begin

  S1 := 'Now is the time for all good men '+
   'to come to the aid of their country.';
  S2 := ;

  for C in S1 do
    S2 := S2 + C;

  if S1 = S2 then
    WriteLn('SUCCESS #1')
  else
    WriteLn('FAIL #1');

  OS1 := 'When in the course of human events'+
   ' it becomes necessary to dissolve...';
  OS2 := ;

  for AC in OS1 do
    OS2 := OS2 + AC;

  if OS1 = OS2 then
    WriteLn('SUCCESS #2')
  else
    WriteLn('FAIL #2');

end. 
Следующий пример показывает итерации по выражениям типа множество:
type

  TMyThing = (one, two, three);
  TMySet   = set of TMyThing;
  TCharSet = set of Char;

var
  MySet:   TMySet;
  MyThing: TMyThing;

  CharSet: TCharSet;
  {$IF DEFINED(CLR)}
  C: AnsiChar;
  {$ELSE}
  C: Char;
  {$IFEND}

begin

  MySet := [one, two, three];
  for MyThing in MySet do
   begin
    // Do something with MyThing...
   end;


  CharSet := [#0..#255];
  for C in CharSet do
    begin
      // Do something with C...
    end;

end. 

Для того, чтобы использовать конструкцию for-in с классами или интерфейсами, класс или интерфейс должны реализовывать соответсвующий функционал коллекции. Тип, который реализует функционал коллекции должен иметь следующие атрибуты:

  • Экземпляр класса или интерфейса должен иметь общедоступный (public) метод с именем GetEnumerator(). Метод GetEnumerator() должен возвращать класс, интерфейс или запись.
  • Экемпляр класса, интерфейса или записи, возвращаемые методом GetEnumerator() должны иметь метод MoveNext(). Метод MoveNext() должен возвращать значение типа Boolean.
  • Экземпляр класса, интерфейса или записи, возвращаемые GetEnumerator() должны содержать доступное только для чтения свойство Current, которое должно возвращать значение типа, содержащегося в коллекции.
Следующий пример демонстрирует итерации по порядковому контейнеру в Delphi.
type
  TMyIntArray = array of Integer;

  TMyEnumerator = class
    Values: TMyIntArray;
    Index:  Integer;
  public
    constructor Create;
    function GetCurrent: Integer;
    function MoveNext:   Boolean;
    property Current:    Integer read GetCurrent;
  end;

  TMyContainer  = class
  public
   function GetEnumerator: TMyEnumerator;
  end;

constructor TMyEnumerator.Create;
begin
  inherited Create;
  Values := TMyIntArray.Create(100, 200, 300);
  Index := -1;
end;

function TMyEnumerator.MoveNext: Boolean;
begin
  if Index < High(Values) then
    begin
      Inc(Index);
      Result := True;
    end
  else
    Result := False;
end;

function TMyEnumerator.GetCurrent: Integer;
begin
  Result := Values[Index];
end;

function TMyContainer.GetEnumerator: TMyEnumerator;
begin
  Result := TMyEnumerator.Create;
end;

var
  MyContainer: TMyContainer;
  I: Integer;

  Counter: Integer;

begin
  MyContainer := TMyContainer.Create;

  Counter := 0;
  for I in MyContainer do
    Inc(Counter, I);

  WriteLn('Counter = ', Counter);
end. 
Следующие классы и их потомки поддерживают работу в конструкции for-in:
  • Classes.TList
  • Classes.TCollection
  • Classes.TStrings
  • Classes.TInterfaceList
  • Classes.TComponent
  • Menus.TMenuItem
  • ActnList.TCustomActionList
  • DB.TFields
  • ComCtrls.TListItems
  • ComCtrls.TTreeNodes
  • ComCtrls.TToolBar

1 комментарий:

  1. (Инструкции Case
    .......
    .......
    где selectorExpression это любое выражение порядкового типа, меньшее, чем 32 бита (строковые типы)->(не больше, чем 32 бита)

    ОтветитьУдалить