Существует ли в Delphi универсальный метод foreach, который можно вызывать с помощью анонимной функции - PullRequest
11 голосов
/ 09 марта 2012

Я могу сделать следующее в C ++

for_each(vec->begin(), vec->end(), [](int n){cout << n << " " << endl;});

Я хотел бы сделать то же самое / подобное в Delphi.Я задал вопрос ранее разработчикам на С ++ и хотел привести аналогичный пример в ООП Паскале.Лямбда (анонимный метод) часть вопроса на самом деле не имеет значения, но мне было интересно, могу ли я сделать то же самое в Delphi XE2.было ли оно добавлено.Спасибо.

1 Ответ

9 голосов
/ 09 марта 2012

Вероятно, ближайший аналог Delphi к std::vector<T> равен TList<T>.Вы можете перебирать список с помощью цикла for in:

var
  Item: Integer;
  List: TList<Integer>;
....
for Item in List do
  Writeln(Item);

Если у вас динамический массив, а не TList<T>, вы можете использовать for in для перебораэлементы.Фактически, все встроенные контейнеры поддерживают for in, и легко добавить поддержку for in в ваши собственные классы.

В C ++ нет ничего похожего на цикл for in, поэтому идиомаиспользовать алгоритм STL.Вот что заставляет вас использовать анонимную функцию.В Delphi с синтаксисом for in вы можете выразить «итерацию по всем элементам контейнера» естественным образом, не прибегая к анонимным методам.

Обобщения были добавлены в Delphi в Delphi 2009 и цикле for inбыл добавлен в Delphi 2005, так что все это доступно вам в XE.Что бы это ни стоило, анонимность также была добавлена ​​в Delphi 2009.

Что вы должны понимать, так это то, что генерики Delphi менее мощны, чем шаблоны C ++.Хотя вы говорите об универсальном foreach, ваш код не является универсальным в том смысле, что он специализируется на int.Вы могли бы написать универсальную версию своего кода на C ++, но это было бы гораздо сложнее сделать с генериками Delphi из-за присущих им обобщений по сравнению с шаблонами.Попытка написать приведенный выше код в Delphi в общем виде приведет к тому, что вы попытаетесь вызвать Writeln.Хотя это было бы тривиально для шаблонов C ++, к сожалению, недостижимо для дженериков.

Обновление: В комментариях вы спрашиваете, есть ли удобный способ добавить содержимое одного контейнера вдругой.Это делает метод AddRange.TList<T>.AddRange() имеет три перегруженных варианта, которые получают один из следующих входных параметров: array of T, Collection: IEnumerable<T> или Collection: TEnumerable<T>.Все стандартные универсальные контейнеры следуют аналогичному шаблону.

...