Может ли кто-нибудь объяснить мне ienumerable и ienumerator?

IEnumerator

IEnumerator, с другой стороны, является скрытым интерфейсом, который заставляет IEnumerble-foreach-magic работать. Строго говоря, он допускает явные итераторы.

По моему опыту IEnumerator редко используется в общих сценариях из-за его более многословного синтаксиса и немного сбивающей с толку семантики (по крайней мере для меня; например, MoveNext () возвращает значение, которое имя не предлагает вообще).

Вариант использования для IEnumerator

Я использовал только IEnumerator в частности (немного более низкого уровня) библиотеки и инфраструктуры, где я предоставлял IEnumerable интерфейсы. Одним из примеров является библиотека обработки потока данных, которая предоставляла серии объектов в цикле , хотя данные за сценой собирались с использованием различных файловых потоков и сериализаций.

Код клиента

Библиотека

IQueryable

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

Разница между IQueryable и IEnumerable

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

IEnumerable

  1. IEnumerable может двигаться только вперед по коллекции, он не может идти назад
  2. Хорошо подходит для работы с данными в памяти (списки, массивы)
  3. Подходит для LINQ to Object и LINQ to XML
  4. Поддерживает отложенное выполнение
  5. Не поддерживает произвольные запросы
  6. Не поддерживает ленивую загрузку
  7. Методы расширения, работающие с IEnumerable принимают функциональные объекты

Код на C#

MyDataContext dc = new MyDataContext ();
IEnumerable<Employee> list = dc.Employees.Where(p => p.Name.StartsWith("S"));
list = list.Take<Employee>(10); 

Сгенерированный SQL

SELECT ., ., . FROM  AS 
WHERE . LIKE @p0

IQueryable

  1. IQueryable может двигаться только вперед по коллекции, он не может идти назад
  2. IQueryable лучше работает с запросами к базе данных (вне памяти)
  3. Подходит для LINQ to SQL
  4. Поддерживает отложенное выполнение
  5. Поддерживает произвольные запросы (используя CreateQuery и метод Execute)
  6. Поддерживает ленивую загрузку
  7. Методы расширения, работающие с IQueryable принимают объекты выражения (expression tree)

Код на C#

MyDataContext dc = new MyDataContext ();
IQueryable<Employee> list = dc.Employees.Where(p => p.Name.StartsWith("S"));
list = list.Take<Employee>(10); 

Сгенерированный SQL

SELECT TOP 10 ., ., . FROM  AS 
WHERE . LIKE @p0

Async/Await и генераторы

Другой крайний случай с forEach() — это то, что он не совсем правильно работает с async/await или генераторами. Если ваш callback forEach() является синхронным, то это не имеет значения, но вы не сможете использовать await внутри callback forEach ():

async function run() {
  const arr = ;
  arr.forEach(el => {
    // SyntaxError
    await new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  });
}

Вы также не сможете использовать yield:

function* run() {
  const arr = ;
  arr.forEach(el => {
    // SyntaxError
    yield new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  });
}

Но приведенные выше примеры отлично работают с for/of:

async function asyncFn() {
  const arr = ;
  for (const el of arr) {
    await new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  }
}

function* generatorFn() {
  const arr = ;
  for (const el of arr) {
    yield new Promise(resolve => setTimeout(resolve, 1000));
    console.log(el);
  }
}

Даже если вы пометите свой callback forEach() как async, вам будет сложно заставить асинхронный метод forEach() работать последовательно. Например, приведенный ниже скрипт будет печатать 0-9 в обратном порядке.

async function print(n) {
  // Wait 1 second before printing 0, 0.9 seconds before printing 1, etc.
  await new Promise(resolve => setTimeout(() => resolve(), 1000 - n * 100));
  // Will usually print 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 but order is not strictly
  // guaranteed.
  console.log(n);
}

async function test() {
  .forEach(print);
}

test();

T

Вывод: если вы используете async/await или генераторы, помните, что forEach() является синтаксическим сахаром. Как сахар, его следует использовать экономно и не для всего.

Объяснение через Analogy + Code Walkthrough

Сначала объяснение без кода, потом я добавлю его позже.

Допустим, вы управляете авиакомпанией. И в каждом самолете вы хотите узнать информацию о пассажирах, летящих в самолете. В основном вы хотите, чтобы иметь возможность «пересечь» самолет. Другими словами, вы хотите иметь возможность начать с переднего сиденья, а затем направиться к задней части самолета, спрашивая пассажиров некоторую информацию: кто они, откуда они и т. Д. Самолет может сделать это только, если это:

  1. исчисляемый и
  2. если у него есть счетчик.

Почему эти требования? Потому что это то, что требует интерфейс.

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

Что значит счетное?

Если авиакомпания является «счетной», это означает, что в самолете ДОЛЖЕН присутствовать стюардесса, единственной задачей которой является подсчет — и эта стюардесса ДОЛЖНА вести подсчет весьма специфическим образом:

  1. Стойка / бортпроводник ДОЛЖНЫ начинать перед первым пассажиром (перед каждым, где они демонстрируют безопасность, как надеть спасательный жилет и т. Д.).
  2. Он / она (т. Е. Стюардесса) ДОЛЖЕН «двигаться дальше» по проходу к первому месту.
  3. Затем он / она должен записать: (i) кто находится на месте, и (ii) его текущее местоположение в проходе.

Процедуры подсчета

Капитан авиакомпании хочет получить отчет о каждом пассажире, когда и когда он расследуется или подсчитывается. Таким образом, после разговора с человеком на первом месте, стюардесса / счетчик затем сообщает капитану, и когда отчет предоставляется, счетчик запоминает его / ее точное положение в проходе и продолжает считать прямо там, где он / она покинул выкл.

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

Счетчик продолжает идти, пока он не достигнет конца самолета.

Давайте свяжем это с IEnumerables

Enumerable — это просто набор пассажиров в самолете. Закон о гражданской авиации — это в основном правила, которым должны следовать все IEnumerables. Каждый раз, когда стюардесса отправляется к капитану с информацией о пассажирах, мы в основном «уступаем» пассажира капитану. Капитан может в основном делать с пассажиром все, что захочет, за исключением перестановки пассажиров в самолете. В этом случае им предоставляется преференциальный режим, если они следуют за Манчестер Сити (тьфу!)
foreach (Passenger passenger in Plane)
// the airline hostess is now at the front of the plane
// and slowly making her way towards the back
// when she get to a particular passenger she gets some information
// about the passenger and then immediately heads to the cabin
// to let the captain decide what to do with it
{ //

Резюме

Другими словами, что-то исчисляется, если у него есть счетчик. И счетчик должен (в основном): (i) помнить свое место (состояние), (ii) быть в состоянии двигаться дальше, (iii) и знать о текущем человеке, с которым он имеет дело.

Enumerable — это просто причудливое слово для «счетного». Другими словами, перечислимое позволяет вам «перечислять» (т.е. считать).

Цикл по ключам и значениям

А что насчет ассоциированных массивов? При использовании такого типа массивов часто нужно иметь доступ к ключу каждого элемента, так же как и к его значению. Конструкция  имеет способ решить поставленную задачу:

foreach ( $array as $key => $value ) {
  // Делаем что-нибудь с $key и/или с $value
}

// Здесь код выполняется после завершения цикла

Пример организации цикла по ассоциированному массиву с информацией о кинофильмах, выводит ключ каждого элемента и его значение в HTML списке определений:

$movie = array( "title" => "Rear Window",
                "director" => "Alfred Hitchcock",
                "year" => 1954,
                "minutes" => 112 );

echo "<dl>";

foreach ( $movie as $key => $value ) {
  echo "<dt>$key:</dt>";
  echo "<dd>$value</dd>";
}

echo "</dl>";

Данный скрипт при выполнении выведет:

title:
    Rear Window
director:
    Alfred Hitchcock
year:
    1954
minutes:
    112

5 последних уроков рубрики «PHP»

Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.

Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак

В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение

В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

5 последних уроков рубрики «PHP»

Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.

Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак

В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение

В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

Цикл по значениям элементов

Самый простой случай использования   — это организация цикла по значениям в индексированном массиве. Основной синтаксис :

foreach ( $array as $value ) {
  // Делаем что-нибудь с  $value
}

// Здесь код выполняется после завершения цикла

Например, следующий скрипт проходит по списку режисеров в индексированном массиве и выводит имя каждого:

$directors = array( "Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang" );

foreach ( $directors as $director ) {
  echo $director . "<br />";
}

Выше приведенный код выведет:

Alfred Hitchcock
Stanley Kubrick
Martin Scorsese
Fritz Lang

Цикл foreach и ключевое слово auto

Поскольку объявляемый элемент цикла foreach должен быть того же типа, что и элементы массива, то это идеальный случай для использования ключевого слова auto, когда мы позволяем C++ вычислить тип данных элементов массива вместо нас. Например:

#include <iostream>

int main()
{
int math[] = { 0, 1, 4, 5, 7, 8, 10, 12, 15, 17, 30, 41 };
for (auto number : math) // тип number определяется автоматически исходя из типа элементов массива math
std::cout << number << ‘ ‘;

return 0;
}

1
2
3
4
5
6
7
8
9
10

#include <iostream>

intmain()

{

intmath={,1,4,5,7,8,10,12,15,17,30,41};

for(auto numbermath)// тип number определяется автоматически исходя из типа элементов массива math

std::cout<<number<<‘ ‘;

return;

}

Цикл foreach

На уроке №76 мы рассматривали примеры использования цикла for для осуществления итерации по каждому элементу массива. Например:

#include <iostream>

int main()
{
const int numStudents = 7;
int scores = { 45, 87, 55, 68, 80, 90, 58 };
int maxScore = 0; // отслеживаем наивысший балл
for (int student = 0; student < numStudents; ++student)
if (scores > maxScore)
maxScore = scores;

std::cout << «The best score was » << maxScore << ‘\n’;

return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include <iostream>

intmain()

{

constintnumStudents=7;

intscoresnumStudents={45,87,55,68,80,90,58};

intmaxScore=;// отслеживаем наивысший балл

for(intstudent=;student<numStudents;++student)

if(scoresstudent>maxScore)

maxScore=scoresstudent;

std::cout<<«The best score was «<<maxScore<<‘\n’;

return;

}

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

Поэтому в C++11 добавили новый тип цикла — foreach (или «цикл, основанный на диапазоне»), который предоставляет более простой и безопасный способ итерации по массиву (или по любой другой структуре типа списка).

Синтаксис цикла foreach следующий:

Выполняется итерация по каждому элементу массива, присваивая значение текущего элемента массива переменной, объявленной как элемент (). В целях улучшения производительности объявляемый элемент должен быть того же типа, что и элементы массива, иначе произойдет неявное преобразование. Рассмотрим простой пример использования цикла foreach для вывода всех элементов массива :

#include <iostream>

int main()
{
int math[] = { 0, 1, 4, 5, 7, 8, 10, 12, 15, 17, 30, 41};
for (int number : math) // итерация по массиву math
std::cout << number << ‘ ‘; // получаем доступ к элементу массива в этой итерации через переменную number

return 0;
}

1
2
3
4
5
6
7
8
9
10

#include <iostream>

intmain()

{

intmath={,1,4,5,7,8,10,12,15,17,30,41};

for(intnumbermath)// итерация по массиву math

std::cout<<number<<‘ ‘;// получаем доступ к элементу массива в этой итерации через переменную number

return;

}

Результат выполнения программы:

Рассмотрим детально, как это всё работает. При выполнении цикла foreach переменной присваивается значение первого элемента (т.е. значение ). Дальше программа выполняет стейтмент вывода значения переменной , т.е. нуля. Затем цикл выполняется снова, и значением переменной уже является (второй элемент массива). Вывод значения выполняется снова. Цикл продолжает свое выполнение до тех пор, пока в массиве не останется непройденных элементов. В конце выполнения программа возвращает обратно в операционную систему с помощью оператора return.

Обратите внимание, переменная не является индексом массива. Ей просто присваивается значение элемента массива в текущей итерации цикла

Цикл foreach PHP — примеры изменения значения элемента массива

Также c помощью php foreach array можно изменять значения элементов массива. Для этого используется «&» перед «$» для переменной значения. Например:

&$value_of_element

Значение будет изменено. Чтобы вам было понятнее, рассмотрим следующий пример.

В этом примере мы создали числовой массив из пяти элементов. После этого использовали цикл foreach для отображения значений элементов.

Затем создали еще один цикл foreach, где перед $value_of_element добавляется «&«. Внутри фигурных скобок присваиваем новые значения элементам массива.

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

Посмотреть демо-версию и код

Пустые элементы

Массивы JavaScript допускают пустые элементы. Массив ниже синтаксически верный и имеет длину 3 элемента:

const arr = ;

arr.length; // 3

Что еще более запутывает, так это то, что циклические конструкции трактуют иначе, чем . Ниже показано, как четыре циклических конструкции обрабатывают с пустым элементом. for/in и for/each пропускают пустой элемент, for и for/of — нет.

// Prints "a, undefined, c"
for (let i = 0; i < arr.length; ++i) {
  console.log(arr);
}

// Prints "a, c"
arr.forEach(v => console.log(v));

// Prints "a, c"
for (let i in arr) {
  console.log(arr);
}

// Prints "a, undefined, c"
for (const v of arr) {
  console.log(v);
}

Если вам интересно, все 4 конструкции выведут «a, undefined, c» для .

Есть еще один способ добавить пустой элемент в массив:

// Equivalent to ``
const arr = ;
arr = 'e';

forEach() и for/in пропускают пустые элементы в массиве, for и for/of — нет. Поведение forEach() может вызвать проблемы, однако можно заметить, что дыры в массивах JavaScript, как правило, встречаются редко, поскольку они не поддерживаются в JSON:

$ node
> JSON.parse('{"arr":}')
{ arr:  }
> JSON.parse('{"arr":}')
{ arr:  }
> JSON.parse('{"arr":}')
SyntaxError: Unexpected token , in JSON at position 12

Таким образом, вам не нужно особо беспокоиться о дырах в пользовательских данных, если вы не предоставите своим пользователям доступ ко всей среде выполнения JavaScript.

Вывод: for/in и forEach() не реагируют на пустые элементы, также известные как «дыры», в массиве. Редко есть какая-либо причина рассматривать дыры как особый случай, а не рассматривать индекс как значение undefined. Если вы допускаете наличие дыр, ниже приведен пример файла .eslintrc.yml, который запрещает вызов forEach().

parserOptions:
  ecmaVersion: 2018
rules:
  no-restricted-syntax:
    - error
    - selector: CallExpression
      message: Do not use `forEach()`, use `for/of` instead

Цикл foreach и не массивы

Циклы foreach работают не только с фиксированными массивами, но также и со многими другими структурами типа списка такими, как векторы (например, std::vector), связанные списки, деревья. Не беспокойтесь, если вы не знаете, что это такое (мы всё это рассмотрим чуть позже). Просто помните, что циклы foreach обеспечивают гибкий и удобный способ итерации не только по массивам:

#include
#include

int main()
{
std::vector math = { 0, 1, 4, 5, 7, 8, 10, 12, 15, 17, 30, 41}; // обратите внимание здесь на использование std::vector вместо фиксированного массива
for (const auto &number : math)
std::cout

1
2
3
4
5
6
7
8
9
10
11

#include
#include

intmain()

{

std::vectormath={,1,4,5,7,8,10,12,15,17,30,41};// обратите внимание здесь на использование std::vector вместо фиксированного массива

for(constauto&numbermath)

std::cout

5 ответов

Лучший ответ

Это языковая конструкция, компилятор точно знает, что должен делать цикл foreach и что такое . Поэтому он может помешать вам изменить переменную итерации .

Это обычный вызов функции, передаваемый в лямбде. Совершенно верно модифицировать локальные переменные в функции (или лямбде), поэтому изменение можно. Хотя компилятор мог предупредить вас, что инкремент не имеет никакого эффекта, поскольку он никогда не использовался впоследствии, он является допустимым кодом, и только потому, что функция называется и фактически делает что-то похожее на foreach -loop не меняет того факта, что это обычная функция и обычная лямбда.

2

tkausl
23 Янв 2019 в 11:52

Оба это разные вещи.

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

Таким образом, одним из подходов может быть, если целью является мутация:

Во-вторых, если целью является получение новой коллекции с обновленными значениями, рассмотрите возможность использования метода linq , который вернет новую коллекцию .

РЕДАКТИРОВАТЬ:

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

Ehsan Sajjad
23 Янв 2019 в 11:55

Как указывает @tkausl, с является локальной переменной. Следовательно:

Будет выводить:

То есть вы не меняете значения .

Rafalon
23 Янв 2019 в 11:51

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

Если вы хотите изменить значение, вы также можете использовать

Обновление

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

и оба выглядят одинаково, но по-разному работают.

habib
23 Янв 2019 в 12:04

не идентичен циклу . Это метод расширения, который будет выполнять итерацию коллекции и выполнять действия с каждым из ее элементов.

Однако не будет изменять коллекцию actuzal, она просто переназначит новое значение , которое не имеет отношения к базовому значению в массиве, потому что это тип значения, который ** копируется * в анонимный метод. Поэтому все, что вы делаете с параметром в вашем анонимном методе, не отражается на — методе и, следовательно, не влияет на ваш массив. Вот почему вы можете сделать это.

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

Взгляните на этот упрощенный пример:

В вашем случае действие выглядит так:

Который просто присваивает новое значение . Однако, поскольку передается по значению , это не повлияет на вызывающий метод и, следовательно, на .

HimBromBeere
23 Янв 2019 в 11:51

Цикл по значениям элементов

Самый простой случай использования   — это организация цикла по значениям в индексированном массиве. Основной синтаксис :

foreach ( $array as $value ) {
  // Делаем что-нибудь с  $value
}

// Здесь код выполняется после завершения цикла

Например, следующий скрипт проходит по списку режисеров в индексированном массиве и выводит имя каждого:

$directors = array( "Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang" );

foreach ( $directors as $director ) {
  echo $director . "<br />";
}

Выше приведенный код выведет:

Alfred Hitchcock
Stanley Kubrick
Martin Scorsese
Fritz Lang

7 ответов

Лучший ответ

Вот как шаблон перечислителя может быть реализован в вашем примере. Я надеюсь, что это проясняет некоторые вещи, в частности, взаимосвязь между и :

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

Поскольку C # поддерживает ключевое слово , создание перечислителя в последнее время стало немного проще:

2

Heinzi
2 Ноя 2011 в 15:48

Предположим, вы должны создать собственную коллекцию костюмов … изучение того, как реализовать , даст вам некоторое представление о том, почему это так полезно. Без него LINQ не мог бы существовать в том виде, в каком мы его знаем.

IAbstract
2 Ноя 2011 в 15:39

Если вы посмотрите на System.Array, вы увидите, что Array реализует IEnumerable. И для каждого не нужен объект IEnumerable. Ему нужен только метод GetEnumerator.

Toto
2 Ноя 2011 в 15:37

Это хорошо, потому что ваш код зависит от интерфейса ()

Сегодняшний тип костюмов в вашем коде — это массив

Если вы решите использовать цикл for, ваш код будет выглядеть примерно так, как показано ниже

В следующем году у вас может быть причина изменить его тип с на . Если вы используете для, вам необходимо обновить блок кода, так как Array имеет , а List имеет свойство .

1

Ekk
2 Ноя 2011 в 16:02

Компилятор C # преобразует это:

Исключение составляет итерация, выполняемая с массивами, которые компилятор обрабатывает по-разному (спасибо @Jon Skeet).

1

Oded
2 Ноя 2011 в 15:47

Вам может (и часто придется) выполнить некоторые более сложные операции, чем просто распечатать значения ваших объектов.

Ваш класс может возвращать (выдавать) объекты один за другим для некоторой внешней обработки (каким-либо другим классом, методом и т. Д.).

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

1

Konrad Morawski
2 Ноя 2011 в 15:40

Прежде всего, если вы собираетесь создать свой собственный перечислитель, вы должны заставить класс реализовать интерфейс IEnumerator (или его общий эквивалент).

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

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

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

2

Joshua Marble
2 Ноя 2011 в 15:40

Заключение

Как правило, for/of — это самый надежный способ перебора массива в JavaScript. Он более лаконичен, чем обычный цикл for, и не имеет такого количества граничных случаев, как for/in и forEach(). Основным недостатком for/of является то, что вам нужно проделать дополнительную работу для доступа к индексу массива (см. дополнение), и вы не можете строить цепочки кода, как вы можете это делать с помощью forEach(). Но если вы знаете все особенности forEach(), то во многих случаях его использование делает код более лаконичным.

Дополнение: Чтобы получить доступ к текущему индексу массива в цикле for/of, вы можете использовать функцию  .

for (const  of arr.entries()) {
  console.log(i, v); // Prints "0 a", "1 b", "2 c"
}

Оригинал: For vs forEach() vs for/in vs for/of in JavaScript

Spread the love

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: