Выражение лямбда с использованием предложения Foreach

Возможный дубликат:
Почему в интерфейсе IEnumerable нет метода расширения ForEach?

ИЗМЕНИТЬ

Для справки, здесь сообщение в блоге, которое eric ссылается на комментарии

http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

ORIG

Больше любопытства, я полагаю, но один для Savants Specification С#...

Почему предложение ForEach() не работает (или недоступно) для использования в наборах результатов IQueryable/IEnumerable...

Вы должны сначала преобразовать результаты ToList() или ToArray() Предположительно, это техническое ограничение на то, как С# выполняет итерацию IEnumerables Vs. Списки... Это как-то связано с отложенным выполнением IEnumerables/IQuerable Collections. например.

var userAgentStrings = uasdc.UserAgentStrings
    .Where<UserAgentString>(p => p.DeviceID == 0 && 
                            !p.UserAgentString1.Contains("msie"));
//WORKS            
userAgentStrings.ToList().ForEach(uas => ProcessUserAgentString(uas));         

//WORKS
Array.ForEach(userAgentStrings.ToArray(), uas => ProcessUserAgentString(uas));

//Doesn't WORK
userAgentStrings.ForEach(uas => ProcessUserAgentString(uas));

Ответ 1

Какое удивительное совпадение, я только что написал статью в блоге по этому самому вопросу. Это будет опубликовано 18 мая. Нет никаких технических причин, по которым мы (или вы!) Не могли этого сделать. Причины, по которым они не являются философскими. Смотрите мой блог на следующей неделе для моего аргумента.

Ответ 2

Совершенно можно написать метод расширения ForEach для IEnumerable<T>.

Я не уверен, почему он не включен как встроенный метод расширения:

  • Возможно, потому что ForEach уже существовал на List<T> и Array до LINQ.
  • Может быть, потому что достаточно просто использовать цикл ForEach для итерации последовательности.
  • Возможно, потому, что не было функционально /LINQy.
  • Может быть, потому что он не связан с цепью. (Легко сделать цепочку для версии yield каждого элемента после выполнения действия, но это поведение не особенно интуитивно понятно.)

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

    foreach (T item in source)
    {
        action(item);
    }
}