Почему ForEach Linq Extension on List, а не IEnumerable

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

Здравствуйте,

Мой вопрос в том, почему метод расширения Foreach определен в List, а не в IEnumreable. я прочитал статью Эрика Липперта но дело в том, что если такой метод настолько плох, чтобы его можно было найти для List?

Ответ 1

List<T>.ForEach() не является методом расширения. Это всего лишь метод на List<T>.

Одна из основных причин, по которой он недоступен в LINQ (т.е. Enumerable), заключается в том, что запросы LINQ должны быть свободны от побочных эффектов (так что вы можете, например, выполнить запрос несколько раз и получить те же результаты без их изменения), что делает их очень сложными. Все операции LINQ, принимающие делегаты, относятся к Func; ни один из них не принимает делегата Action.

Ответ 2

Это была ошибка, которую я опубликовал на веб-сайте Microsoft Connect. Microsoft уже исправила ее в предстоящей версии .NET Edition, как указано здесь в следующей ссылке.

List.ForEach позволяет перечислять измененную версию списка

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

ForEach, удалить (работает)

List<int> list = new List<int>(){ 1, 2, 3, 4, 5, 6};

list.ForEach(x => {
    Console.WriteLine(x);
    list.Remove(x);
});

foreach, удалить (сбой)

// throws exception
foreach (var x in list)
{
    Console.WriteLine(x);
    list.Remove(x);
}

ForEach, вставьте (...)

// goes in infinite loop...
list.ForEach(x => {
    list.Add(1);
});

foreach, вставить (сбой)

// throws exception
foreach (var x in list)
{
    Console.WriteLine(x);
    list.Add(x);
}

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

Несмотря на аргументы, я по-прежнему не вижу причин, по которым ForEach должен допускать модификации, он чисто используется для перечисления, и не имеет значения, является ли синтаксис foreach (var item in x) или x.ForEach(x = > {}).

Я не согласен с Эриком, я просто вижу, что команда BCL реализовала эту функцию в IEnumerable, а также list.ForEach неисправен.

"Почему" является полностью субъективным, например, Silverlight добавляет сложные алгоритмы хэширования и оставляет MD5 позади, где еще везде мы используем MD5 так широко. Его больше того, сколько чего угодно востребовано, и кто выбирает, включать ли его в рамки или нет.

Существует никакой логической или философской причины вообще, поскольку у меня нет ForEach в IEnumerable. Есть много таких недостающих точек, которые, я думаю,.NET со временем улучшатся.

Ответ 3

То, что происходит, - это состояние мутации, использующее LINQ, следует избегать и не поощрять, фокус LINQ - это запрос и преобразование данных, но не на месте мутации - вы теряете многие преимущества функционального подхода LINQs (то есть никаких побочных эффектов, тот же ввод производит тот же вывод), если вы изменяете состояние.

Нет преимущества Linq, предлагающего метод расширения ForEach() в обычном цикле foreach, отличный от того, что он помог бы вам в мутирующем состоянии - следовательно, он не был реализован (по крайней мере, я возьму его, возьмите с собой зерно соли).

Ответ 4

"Почему" не входит в мою сферу; Я не делал С#. Тем не менее, это имеет смысл, поскольку он будет перечислять вашу коллекцию, в то время как большинство операторов LINQ лениво оцениваются.