Есть ли итератор .Each() (или .ForEach()) в стандартной библиотеке .Net?
Возможный дубликат:
LINQ эквивалент foreach для IEnumerable <T>
Мне интересно, есть ли метод IEnumerable, например, следующий .Each() в библиотеке .Net
var intArray = new [] {1, 2, 3, 4};
intArrary.Each(Console.WriteLine);
Я знаю, что могу использовать цикл foreach
или легко написать метод расширения следующим образом:
public static class EnumerableExtensions
{
public static void Each<T>(this IEnumerable<T> enumberable, Action<T> action)
{
foreach (var item in enumberable)
{
action(item);
}
}
}
Но я надеюсь не создавать свой собственный метод, чтобы испортить код, если в библиотеке уже есть такой метод расширения. И что-то вроде .Each() (с несколькими перегрузками, которые могут принимать условия в качестве дополнительных параметров) в значительной степени необходимы программистам, и их уже должно быть. Правильно ли я?
Обновление
Разработчики Ruby могут распознать его как .each() итератор. И это то, что я надеюсь иметь на С#. Возможно, С# может иметь больше методов итератора, например, в Ruby.
Ответы
Ответ 1
Как говорили другие, на IEnumerable<T>
нет встроенного. Команда Linq была против этого, как в этом сообщении Эрика Липперта::
http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
Существует статический метод на Array.ForEach
, а List<T>
- метод экземпляра. Есть также в PLINQ foreach как заявления, но имейте в виду, что они работают параллельно и могут привести к очень плохой производительности для чрезвычайно простых действий.
Вот один из таких методов в PLINQ: http://msdn.microsoft.com/en-us/library/dd383744.aspx
И вот руководство по PLINQ в целом: http://msdn.microsoft.com/en-us/library/dd460688.aspx
Пока я не могу найти точную статью, если вы соскучились в секции ParrallelEnumerable, она дает предупреждения и советы о том, как повысить производительность использования parallelism в коде
Если вы этого хотите, я предлагаю создать 2 версии, в том числе индексатора и без нее. Это может быть весьма полезным и может сохранить оператор select для получения индекса.
например.
public static void ForEach<T>(IEnumerable<T> enumerable,Action<T> action)
{
foreach(var item in enumerable) action(item);
}
public static void ForEach<T>(IEnumerable<T> enumerable,Action<T,int> action)
{
int index = 0;
foreach(var item in enumerable) action(item,index++);
}
Я бы также включил проверку аргументов, поскольку это общедоступные методы.
Ответ 2
Да, есть.
someList.ForEach(x => Console.WriteLine(x));
Или с массивом:
Array.ForEach(someArray, x => Console.WriteLine(x));
Обратите внимание, что в этом последнем примере вам нужно вызвать статический метод в классе Array
EDIT: пространства имен: System.Collections.Generic для метода List и System для метода Array
Ответ 3
Существует метод ForEach в System.Collections.List <T> , но не на IEnumerable. Обратите внимание, что это также не часть LINQ (она уже была в .NET 2.0).
На первый взгляд вы ожидаете, что это будет часть LINQ, так как это будет расширение для нормальной функции списка. Однако LINQ больше связан с группировкой, фильтрацией и преобразованием данных. Если вы внимательно присмотритесь, большинство (если не все, я не Джон Скит, я не знаю этого наизусть!) Методы LINQ возвращают некоторый тип IEnumerable.
Однако вы можете взглянуть на MoreLinq. Это проект с открытым исходным кодом, который добавляет некоторые ключевые функции в существующий LINQ to Objects, один из которых - это метод ForEach, который вы хотите (работает в любом IEnumerable в этом случае, поэтому он также будет работать и с вашим массивом).
Ответ 4
Нет, к сожалению, нет. (Я думаю, этот вопрос обсуждался ранее, но я не могу найти его в настоящее время.)
Из-за какой-то странной случайности история ForEach
оказалась в List<T>
вместо IEnumerable<T>
, где это будет иметь больше смысла, и из-за обратной совместимости это никогда не может быть исправлено.
С тех пор, как существовали методы расширения, добавление метода расширения ForEach(this IEnumerable<T>, ...)
было запрошено снова и снова, но оно обычно отклоняется, потому что это приведет к запутанному поведению: поскольку методы экземпляра всегда выбираются перед методами расширения, это будет означать, что все IEnumerable
обрабатываются одинаково, кроме List
, и они не допускают таких несоответствий в BCL.
В результате почти каждый проект .NET на планете теперь начинается именно с кода, описанного выше:
namespace IEnumerableExtensions
{
public static class IEnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> xs, Action<T> f)
{
foreach (var x in xs) f(x);
}
}
}
Ответ 5
Только List<T>
предоставляет ForEach
метод - для всех остальных типов вам придется перевернуть свой собственный метод расширения.
Ответ 6
это зависит от версии рамки
.net 3.5 и 4.0 имеют метод ForEach