foreach vs someList.ForEach () {}

Вернувшись в более старые версии Delphi, которые не поддерживали записи с помощью методов, тогда использование object было способом получить ваши объекты, выделенные в стеке. Очень редко это могло бы принести пользу производительности. В настоящее время record лучше. Единственная функция, отсутствующая в record, - это способность наследовать от другого record.

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

142
задан Peter Bruins 1 November 2017 в 11:18
поделиться

10 ответов

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

Таким образом, у Вас есть другой делегат (=method) вызов.

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

1
ответ дан EFrank 1 November 2017 в 11:18
поделиться

Одна вещь опасаться состоит в том, как выйти из Универсального.ForEach метода - см. это обсуждение . Хотя в ссылке, кажется, говорится, что этот путь самый быстрый. Не уверенный, почему - Вы думали бы, что они будут эквивалентны когда-то скомпилированные...

1
ответ дан Chris Kimpton 1 November 2017 в 11:18
поделиться

Между двумя существует одно важное, и полезное, различие.

, поскольку.ForEach использует for цикл для итерации набора, это допустимо (редактирование: до .net 4.5 - измененная реализация и они оба бросок):

someList.ForEach(x => { if(x.RemoveMe) someList.Remove(x); }); 

, тогда как foreach использование перечислитель, таким образом, это не допустимо:

foreach(var item in someList)
  if(item.RemoveMe) someList.Remove(item);
<час>

tl; доктор: НЕ Делайте copypaste этот код в Ваше приложение!

Этими примерами не является лучшая практика, они должны только продемонстрировать различия между ForEach() и foreach.

объекты Удаления из списка в for цикл может иметь побочные эффекты. Наиболее распространенный описан в комментариях к этому вопросу.

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

121
ответ дан Will 1 November 2017 в 11:18
поделиться
  • 1
    Не берите в голову, что я понял его =ARRAYFORMULA (ЕСЛИ (F2:F ="? " "? " F2:F - E2:E)) Большое спасибо за указание на меня в правильном направлении. – slister 27 September 2013 в 13:16

Список. ForEach () считается более функциональным.

List.ForEach() говорит, что Вы хотите сделанный. foreach(item in list) также говорит точно, как Вы хотите сделанный. Это уезжает List.ForEach свободный изменить реализацию как часть в будущем. Например, гипотетическая будущая версия.Net могла бы всегда работать List.ForEach параллельно под предположением, что в этой точке у всех есть много ядер CPU, которые обычно простаивают.

, С другой стороны, foreach (item in list) дает Вам немного больше контроля циклом. Например, Вы знаете, что объекты будут выполнены с помощью итераций в некотором последовательном порядке, и Вы могли легко прервать середину, если объект удовлетворяет некоторому условию.

2
ответ дан Joel Coehoorn 1 November 2017 в 11:18
поделиться

Я предполагаю эти someList.ForEach(), вызов мог быть легко параллелизирован, тогда как нормальное foreach не настолько легко идти параллельно. Вы могли легко выполнить несколько различных делегатов на различных ядрах, который не настолько легко сделать с нормальным foreach.
Просто мои 2 цента

10
ответ дан Paul Chu 1 November 2017 в 11:18
поделиться
  • 1
    Это работает большое спасибо. С этим методом я использовал бы OpenRowset, OPENXML или объем загружаются для вкладывания данных из файла? – pugu 30 May 2013 в 14:55

Негласно, в анонимного делегата превращаются фактический метод, таким образом, у Вас могли быть немного служебные со вторым выбором, если бы компилятор не принимал решение встроить функцию. Кроме того, любые локальные переменные, на которые ссылается тело анонимного примера делегата, изменились бы по своей природе из-за приемов компилятора для сокрытия того, что это компилируется в новый метод. Больше информации здесь о том, как C# делает это волшебство:

http://blogs.msdn.com/oldnewthing/archive/2006/08/04/688527.aspx

2
ответ дан jezell 1 November 2017 в 11:18
поделиться
  • 1
    Как реализация нейтрализация JavaScript? – user2264703 13 May 2013 в 08:46

Я знаю две вещи неясного выхода, которые делают их отличающимися. Пойдите меня!

Во-первых, существует классическая ошибка создания делегата к каждому объекту в списке. Если Вы используете foreach ключевое слово, все Ваши делегаты могут закончить тем, что обратились к последнему объекту списка:

    // A list of actions to execute later
    List<Action> actions = new List<Action>();

    // Numbers 0 to 9
    List<int> numbers = Enumerable.Range(0, 10).ToList();

    // Store an action that prints each number (WRONG!)
    foreach (int number in numbers)
        actions.Add(() => Console.WriteLine(number));

    // Run the actions, we actually print 10 copies of "9"
    foreach (Action action in actions)
        action();

    // So try again
    actions.Clear();

    // Store an action that prints each number (RIGHT!)
    numbers.ForEach(number =>
        actions.Add(() => Console.WriteLine(number)));

    // Run the actions
    foreach (Action action in actions)
        action();

Список. Метод ForEach не имеет этой проблемы. Текущий объект повторения передается значением как аргумент внешней лямбде, и затем внутренняя лямбда правильно получает тот аргумент в своем собственном закрытии. Проблема решена.

(Печально я верю, ForEach является членом Списка, а не дополнительного метода, хотя легко определить его самостоятельно, таким образом, у Вас есть это средство на любом перечислимом типе.)

, Во-вторых, подход метода ForEach имеет ограничение. При реализации IEnumerable при помощи возврата урожая Вы не можете сделать возврата урожая в лямбде. Таким образом, цикличное выполнение через объекты в наборе для получения вещей возврата не возможно этим методом. Необходимо будет использовать foreach ключевое слово и работу вокруг проблемы закрытия путем ручного создания копии текущего значения цикла в цикле.

Больше здесь

11
ответ дан Daniel Earwicker 1 November 2017 в 11:18
поделиться
  • 1
    Нейтрализация JavaScript должна добавить onChange обработчик событий к Вашему полю ввода и проверить число (попытайтесь анализировать его к целому числу сначала и затем проверьте если it' s выше нуля). – g00glen00b 14 May 2013 в 21:04

Для забавы я вытолкал Список в отражатель, и это - получающийся C#:

public void ForEach(Action<T> action)
{
    if (action == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    for (int i = 0; i < this._size; i++)
    {
        action(this._items[i]);
    }
}

Точно так же MoveNext в Перечислителе, который является тем, что используется foreach, является этим:

public bool MoveNext()
{
    if (this.version != this.list._version)
    {
        ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
    }
    if (this.index < this.list._size)
    {
        this.current = this.list._items[this.index];
        this.index++;
        return true;
    }
    this.index = this.list._size + 1;
    this.current = default(T);
    return false;
}

Список. ForEach намного более обрезается вниз, чем MoveNext - намного меньше обработки - будет более вероятный JIT во что-то эффективное..

, Кроме того, foreach () выделит новый Перечислитель несмотря ни на что., GC является Вашим другом, но если Вы сделаете тот же foreach неоднократно, это сделает больше холостых объектов, в противоположность многократному использованию того же делегата - , НО - это - действительно случай края. В типичном использовании Вы будете видеть минимальное различие.

16
ответ дан plinth 1 November 2017 в 11:18
поделиться
  • 1
    @pugu: обновленный мой ответ - использование OPENROWSET(BULK .....) для загрузки файла из диска – marc_s 30 May 2013 в 15:04

У нас был некоторый код здесь (в VS2005 и C#2.0), где предыдущие инженеры старались изо всех сил использовать list.ForEach( delegate(item) { foo;}); вместо foreach(item in list) {foo; }; для всего кода, который они записали. например, блок кода для чтения строк от dataReader.

я все еще не знаю точно, почему они сделали это.

недостатки list.ForEach():

  • Это является более подробным в C# 2.0. Однако в C# 3 вперед, можно использовать" =>" синтаксис для создания некоторых приятно кратких выражений.

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

  • См. также книгу Bill Wagner "Эффективный C#: 50 Особенных методов Улучшить Ваш C#", где он говорит о том, почему foreach предпочтен другим циклам как для или циклы с условием продолжения - основной момент, состоят в том, что Вы позволяете компилятору решить лучший способ создать цикл. Если будущей версии компилятора удастся использовать более быструю технику, то Вы получите это бесплатно при помощи foreach и восстановления, вместо того, чтобы изменить Ваш код.

  • foreach(item in list) конструкция позволяет Вам использовать break или continue, если необходимо выйти из повторения или цикла. Но Вы не можете изменить список в цикле foreach.

я удивлен видеть, что list.ForEach немного быстрее. Но это - вероятно, не допустимая причина использовать его повсюду, который был бы преждевременной оптимизацией. Если Ваше приложение использует базу данных или веб-сервис, который, не управление циклом, почти всегда будет, то, куда время проходит. И Вы сравнили его с for цикл также? Эти list.ForEach мог произойти быстрее из-за использования этого внутренне и for, цикл без обертки будет еще быстрее.

я не соглашаюсь, что list.ForEach(delegate) версия "более функциональна" любым значительным способом. Это действительно передает функцию функции, но нет никакой большой разницы в организации программы или результате.

я не думаю, что foreach(item in list), "говорит точно, как Вы хотите сделанный" - for(int 1 = 0; i < count; i++), цикл делает это, foreach, цикл оставляет выбор управления до компилятора.

Мое чувство, на новом проекте, для использования foreach(item in list) для большинства циклов для соблюдения общего использования и для удобочитаемости и использования list.Foreach() только для коротких блоков, когда можно сделать что-то более изящно или сжато с 3 дюймами C# =>" оператор. В случаях как этот может уже быть дополнительный метод LINQ, который более конкретен, чем [1 119]. Посмотрите, не делает ли Where(), Select(), Any(), All(), Max() или один из многих других методов LINQ уже то, что Вы хотите от цикла.

73
ответ дан 10 revs 1 November 2017 в 11:18
поделиться
  • 1
    Проблема с этим методом состоит в том что это doesn' t включают любой из параметров, таких как " Muppets"... – pugu 30 May 2013 в 15:30

Вы могли назвать анонимного делегата:-)

, И можно записать второе как:

someList.ForEach(s => s.ToUpper())

, Который я предпочитаю и сохраняю большой ввод.

, Поскольку Joachim говорит, параллелизм легче относиться к второй форме.

3
ответ дан Craig.Nicol 1 November 2017 в 11:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: