Delphi - сбориник статей

       

For..in..do


В язык Delphi добавлена конструкция for..in..do для перебора всех членов массива, строки, множества или коллекции.

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

То есть, в цикле перебираются все элементы некоего множества и для каждого выполняется тело цикла. Например, теперь ничего не стоит перевернуть строку наоборот (см. )

Полная и весьма понятная информация находится в справке, смотрите раздел "Declarations and Statements"

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

  • содержать public метод экземпляра с именем GetEnumerator, который должен возвращать экземпляр класса, ссылку на интерфейс или запись (record).
  • экземпляр класса, ссылка на интерфейс или запись, возвращенные методом GetEnumerator, должны содержать public метод экземпляра с именем MoveNext, возвращающий значение типа boolean.


  • экземпляр класса, ссылка на интерфейс или запись, возвращенные методом GetEnumerator должны содержать public свойство экземпляра с именем Current, тип которого должен соответствовать типу элементов контейнера.

Экземпляр, возвращенный методом GetEnumerator, автоматически разрушается после окончания цикла for..in.

Следующий пример показывает реализацию паттерна коллекции

program Project1; {$APPTYPE CONSOLE} 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; ar: TMyIntArray; begin MyContainer := TMyContainer.Create; Counter := 0; for I in MyContainer do Inc(Counter, I); WriteLn('Counter = ', Counter); end.

Поддержка синтаксиса for...in уже встроена в ряд классов VCL, например, TList, TComponent, TCollection, и т.д. - в общей сложности около 15 классов. Так, например, перечисление имен компонентов формы может выглядеть следующим образом (хотя и непривычно):

var I: TComponent; begin for I in Self do ListBox.Add (I.Name); end;



Содержание раздела