Почему нет никакого метода расширения ForEach на IEnumerable?

Как будто вы пытаетесь получить доступ к объекту, который является null. Рассмотрим ниже пример:

TypeA objA;

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

См. Также этот пример:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
367
задан bluish 24 August 2015 в 23:44
поделиться

16 ответов

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

я не хотел бы видеть следующее:

list.ForEach( item =>
{
    item.DoSomething();
} );

Вместо:

foreach(Item item in list)
{
     item.DoSomething();
}

последний более ясен и легче читать в большей части ситуации , хотя, возможно, немного дольше ввести.

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

Вот существенные различия между оператором и методом:

  • проверка Типа: foreach сделан во времени выполнения, ForEach () во время компиляции (Большой Плюс!)
  • синтаксис для вызова делегата действительно намного более прост: объекты. ForEach (DoSomething);
  • ForEach () мог быть объединен в цепочку: хотя злой / полноценность такой функции открыто для обсуждения.

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

189
ответ дан Maslow 23 November 2019 в 00:08
поделиться

Если у Вас есть F# (который будет в следующей версии.NET), можно использовать

Seq.iter doSomething myIEnumerable

2
ответ дан vzwick 23 November 2019 в 00:08
поделиться

Никто еще не указал на это ForEach< T> результаты в типе времени компиляции, проверяющем, где foreach ключевое слово является проверенным временем выполнения.

сделавший некоторый рефакторинг, где оба метода использовались в коде, я одобряю.ForEach, поскольку я должен был выследить тестовые отказы / отказы во время выполнения найти foreach проблемы.

0
ответ дан Squirrel 23 November 2019 в 00:08
поделиться

Я записал сообщение в блоге об этом: http://blogs.msdn.com/kirillosenkov/archive/2009/01/31/foreach.aspx

можно голосовать здесь, если требуется видеть этот метод в.NET 4.0: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=279093

2
ответ дан Kirill Osenkov 23 November 2019 в 00:08
поделиться

Он меня или List< T>.Foreach, в значительной степени сделанный устаревшим Linq. Первоначально был

foreach(X x in Y) 

, где Y просто должен был быть IEnumerable (Пред 2,0) и реализовать GetEnumerator (). Если Вы смотрите на MSIL, генерировал Вас, видят, что это - точно то же как

IEnumerator<int> enumerator = list.GetEnumerator();
while (enumerator.MoveNext())
{
    int i = enumerator.Current;

    Console.WriteLine(i);
}

(См. http://alski.net/post/0a-for-foreach-forFirst-forLast0a-0a-.aspx для MSIL)

Тогда в Дженериках DotNet2.0 пришел и Список. Foreach всегда чувствовал мне, чтобы быть реализацией шаблона Vistor, (см. Шаблоны разработки Гаммой, Рулем, Johnson, Vlissides).

Теперь, конечно, в 3,5 мы можем вместо этого использовать Лямбду для того же эффекта для попытки в качестве примера http://dotnet-developments.blogs.techtarget.com/2008/09/02/iterators-lambda-and-linq-oh-my/

2
ответ дан davidsleeps 23 November 2019 в 00:08
поделиться

Можно использовать выбор, когда Вы хотите возвратить что-то. Если Вы не делаете, можно использовать ToList сначала, потому что Вы, вероятно, не хотите изменять что-либо в наборе.

2
ответ дан Paco 23 November 2019 в 00:08
поделиться

Большинство дополнительных методов LINQ возвращает результаты. ForEach не вписывается в этот шаблон, поскольку это ничего не возвращает.

2
ответ дан leppie 23 November 2019 в 00:08
поделиться

Таким образом, было много комментариев о том, что метод расширения ForEach не является соответствующим, потому что он не возвращает значение как дополнительные методы LINQ. В то время как это - фактический оператор, это не совершенно верно.

дополнительные методы LINQ действительно все возвращают значение, таким образом, они могут быть объединены в цепочку вместе:

collection.Where(i => i.Name = "hello").Select(i => i.FullName);

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

определенный arguement о ForEach - то, что, на основе ограничений на дополнительные методы (а именно, что дополнительный метод будет никогда , переопределяют унаследованный метод с та же подпись ), может быть ситуация, где пользовательский дополнительный метод доступен на всех классах что impelement IEnumerable<T> кроме Списка <T>. Это может вызвать беспорядок, когда методы начинают вести себя по-другому в зависимости от того, называют ли дополнительный метод или наследовать метод.

8
ответ дан Scott Dorman 23 November 2019 в 00:08
поделиться

@Coincoin

действительная мощность foreach дополнительного метода включает возможность многократного использования Action<>, не добавляя ненужные методы к Вашему коду. Скажите, что у Вас есть 10 списков, и Вы хотите выполнить ту же логику на них, и соответствующая функция не вписывается в Ваш класс и не снова используется. Вместо того, чтобы иметь десять для циклов или родовой функции, которая является, очевидно, помощником, который не принадлежит, можно сохранить всю логику в одном месте (Action<>. Так, десятки строк заменяются

Action<blah,blah> f = { foo };

List1.ForEach(p => f(p))
List2.ForEach(p => f(p))

и т.д.

, логика находится в одном месте, и Вы не загрязнили свой класс.

4
ответ дан spoulson 23 November 2019 в 00:08
поделиться

Одно обходное решение должно записать .ToList().ForEach(x => ...).

профессионалы

Легкий понять - читатель только должен знать что поставки с C#, не любые дополнительные дополнительные методы.

Синтаксический шум является очень умеренным (только добавляет немного постороннего кода).

обычно не стоит дополнительной памяти, так как собственный компонент .ForEach() должен был бы понять целый набор, так или иначе.

недостатки

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

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

, Если перечисление бесконечно (как натуральные числа), Вы являетесь неудачливыми.

13
ответ дан Jay Bazuzi 23 November 2019 в 00:08
поделиться

Я всегда задавался вопросом, что сам, именно поэтому что я всегда ношу это со мной:

public static void ForEach<T>(this IEnumerable<T> col, Action<T> action)
{
    if (action == null)
    {
        throw new ArgumentNullException("action");
    }
    foreach (var item in col)
    {
        action(item);
    }
}

Миленький дополнительный метод.

13
ответ дан Alexandr Nikitin 23 November 2019 в 00:08
поделиться

В то время как я соглашаюсь, что лучше использовать встроенное foreach конструкция в большинстве случаев, я нахожу использование этого изменения на ForEach<> расширение, чтобы быть немного более хорошим, чем необходимость управлять индексом в постоянном клиенте foreach самостоятельно:

public static int ForEach<T>(this IEnumerable<T> list, Action<int, T> action)
{
    if (action == null) throw new ArgumentNullException("action");

    var index = 0;

    foreach (var elem in list)
        action(index++, elem);

    return index;
}
Пример
var people = new[] { "Moe", "Curly", "Larry" };
people.ForEach((i, p) => Console.WriteLine("Person #{0} is {1}", i, p));

дал бы Вам:

Person #0 is Moe
Person #1 is Curly
Person #2 is Larry
17
ответ дан Chris Zwiryk 23 November 2019 в 00:08
поделиться

обсуждение здесь дает ответ:

На самом деле, определенное обсуждение, которое я засвидетельствовал, действительно на самом деле висело на петлях по функциональной чистоте. В выражении часто существуют предположения, сделанные о не наличии побочных эффектов. Наличие ForEach конкретно приглашает побочные эффекты вместо того, чтобы просто выносить их. - Keith Farmer (Партнер)

В основном решение было принято для хранения дополнительных методов функционально "чистыми". ForEach поощрил бы побочные эффекты при использовании Счетных дополнительных методов, который не был намерением.

33
ответ дан sashoalm 23 November 2019 в 00:08
поделиться

Метод ForEach был добавлен перед LINQ. Если Вы добавите расширение ForEach, это никогда не будут называть для экземпляров Списка из-за дополнительных ограничений методов. Я думаю причина, она не была добавлена, к не интерференция с существующей.

Однако при реальных пропавших без вести этой небольшой хорошей функции можно развернуть собственную версию

public static void ForEach<T>(
    this IEnumerable<T> source,
    Action<T> action)
{
    foreach (T element in source) 
        action(element);
}
73
ответ дан aku 23 November 2019 в 00:08
поделиться

Вы могли записать этот дополнительный метод:

// Possibly call this "Do"
IEnumerable<T> Apply<T> (this IEnumerable<T> source, Action<T> action)
{
    foreach (var e in source)
    {
        action(e);
        yield return e;
    }
}

Профессионалы

Позволяет объединять в цепочку:

MySequence
    .Apply(...)
    .Apply(...)
    .Apply(...);

Недостатки

Это ничего на самом деле не сделает, пока Вы не сделаете что-то для принуждения повторения. По этой причине это нельзя назвать .ForEach(). Вы могли записать .ToList() в конце, или Вы могли записать этот дополнительный метод, также:

// possibly call this "Realize"
IEnumerable<T> Done<T> (this IEnumerable<T> source)
{
    foreach (var e in source)
    {
        // do nothing
        ;
    }

    return source;
}

Это может быть слишком значительным отъездом из поставлющихся библиотек C#; читатели, которые не знакомы с Вашими дополнительными методами, не будут знать, что сделать из Вашего кода.

51
ответ дан Jay Bazuzi 23 November 2019 в 00:08
поделиться

В 3.5, все методы расширения, добавленные в IEnumerable, предназначены для поддержки LINQ (обратите внимание, что они определены в классе System.Linq.Enumerable). В этом посте я объясняю, почему foreach не принадлежит LINQ: Существующий метод расширения LINQ похож на Parallel.For?

2
ответ дан 23 November 2019 в 00:08
поделиться