Почему метод ForEach только для списков - PullRequest
9 голосов
/ 01 февраля 2010

Из того, что я вижу, метод ForEach доступен только для List класса .

Почему это? Я не вижу причин, по которым ForEach не будет доступен ни одному классу, реализующему интерфейсы IEnumerable / IEnumerator, и это действительно полезный метод, если вам нужно выполнить небольшое действие (1 строка более читаема, чем 1 строка + 2 шаблонный синтаксис foreach ...).

Обновление: Я уточню свой вопрос. Есть совершенно веские причины для включения ForEach в последовательности. Есть вполне веские причины для , а не , включая ForEach во всех последовательностях.

Но я не могу понять, почему ForEach было бы включено только в некоторые последовательности.

Ответы [ 5 ]

23 голосов
/ 01 февраля 2010

См. Сообщение Эрика Липперта: "foreach" против "ForEach"

Несколько человек спросили меня, почему Microsoft не предоставляется Расширение оператора последовательности «ForEach» метод. Класс List имеет такой метод уже конечно, но есть нет причин, почему такой метод не мог быть создан как метод расширения для все последовательности.

...

Но мы можем пойти немного глубже. я философски против предоставления такой метод по двум причинам.

...

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

...

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

...

Ну, команда VS Languages ​​не иметь какое-либо влияние на то, что входит в Список. Я лично нахожу Метод ForEach в списке философски беспокоит всех те же причины, по которым я бы нашел метод расширения на IEnumerable беспокойство. (И команда VSL делает контролировать это.) Один смягчающий фактор в том, что список явно разработан, чтобы быть изменчивым, структура данных без побочных эффектов, поэтому с помощью выражений, которые видоизменяют его кажется чуть менее плохим. - Эрик

7 голосов
/ 01 февраля 2010

Вы правы, метод определен в классе List. Однако довольно легко создать метод расширения, который делает то же самое.

public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
    foreach (var t in enumerable)
        action(t);
}
2 голосов
/ 01 февраля 2010

Технически, с .NET 3.5 вы могли бы сделать это: (вам нужно включить System.Linq)

IEnumerable<string> a = ...

a.All(i => { DoSomethingWith(i); return true; });
2 голосов
/ 01 февраля 2010

Правильно. Однако, если вы хотите использовать преимущество цикла ForEach, есть метод с именем «ToList», как показано ниже, который используется для преобразования массива обратно в List.

String[] array = new String[3];
List<String> list = array.ToList<String>();
0 голосов
/ 01 февраля 2010

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

(Это написано для использования с VS 2010 ... если вы используете предыдущую версию, вам, вероятно, потребуется удалить = null из сигнатуры метода)

public static void SafeForEach<T>(this IEnumerable<T> input,
                                       Action<T> action,
                                       Action<T, Exception> faultAction = null)
{
    if (input == null || action == null)
        return;
    foreach (var item in input)
        try
        {
            action(item);
        }
        catch (Exception ex)
        {
            if (faultAction == null)
                Debug.WriteLine(ex);
            else
                faultAction(item, ex);
        }
}
...