2010-11-28 3 views
14

Можно создать дубликат:
LINQ equivalent of foreach for IEnumerable<T>есть итератор .Each() (или .ForEach()) в стандартной библиотеке .Net?

мне интересно, есть ли способ 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() (с несколькими перегрузками, которые могут принимать условия в качестве дополнительных параметров) в значительной степени необходимы программистам, и их уже должно быть. Я прав?

Update

разработчики Рубин может признать его в качестве .each() итератора. И это то, что я надеюсь иметь на C#. Возможно, у C# может быть больше методов итератора, таких как Ruby.

+1

Для списка есть расширение ForEach, которое является стандартным. – 2010-11-28 00:51:23

+1

Возможно, обратите внимание также: http://stackoverflow.com/questions/1924535/c-any-benefit-of-listt-foreach-over-plain-foreach-loop – Brian 2010-11-28 01:07:23

+1

@James ForEach не является расширением. Это всегда было. – RichK 2010-11-28 20:54:21

ответ

9

Как уже сказал, что нет ни построен в на 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 дает предупреждение и советы по повышению эффективности использования параллелизма в коде

Если вы хотите, я предлагаю создать 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++); 
} 

Я бы также включил проверку аргументов, поскольку это общедоступные методы.

5

Да, есть.

someList.ForEach(x => Console.WriteLine(x)); 

Или с массивом:

Array.ForEach(someArray, x => Console.WriteLine(x)); 

Заметим, что в последнем примере вы должны вызвать статический метод в классе Array,

EDIT: Пространства имен: System.Collections .Generic для метода списка и Система для метода массива

+0

Какое пространство имен следует использовать? – Shuo 2010-11-28 00:50:43

+0

-1 ForEach - это метод экземпляра в `List ` - у массивов этот метод экземпляра отсутствует. – 2010-11-28 00:51:36

0

Только List<T> предоставляет метод ForEach - для всех остальных типов вам придется перевернуть свой собственный метод расширения.

0

это зависит от версии рамочного

.net 3.5 и 4.0 имеет ForEach методы

2

Там в методе ForEach на System.Collections.List < T>, но не на IEnumerable. Обратите внимание, что это также не часть LINQ (он уже был в .NET 2.0).

На первый взгляд вы ожидаете, что это будет частью LINQ, поскольку это своего рода расширение для обычных функций списка. Однако LINQ больше связан с группировкой, фильтрацией и преобразованием данных. Если вы посмотрите внимательно, большинство (если не все, я не Джон Скит, я не знаю этого наизусть!) Методы LINQ возвращают некоторый тип IEnumerable.

Однако, возможно, вы захотите взглянуть на MoreLinq. Это проект с открытым исходным кодом, который добавляет некоторые ключевые функции существующим LINQ to Objects, одним из которых является метод ForEach, который вы хотите (работает в любом IEnumerable в этом случае, поэтому он также будет работать и с вашим массивом).

1

Нет, к сожалению, нет.(Я думаю, что этот вопрос обсуждался ранее, но я не могу найти его в настоящее время.)

Из-за какой-то странной случайности истории, метод ForEach оказался на List<T>, вместо IEnumerable<T>, где было бы больше смысла , и из-за обратной совместимости это никогда не может быть исправлено.

С тех пор как существовали методы расширения, добавление метода расширения ForEach(this IEnumerable<T>, ...) было запрошено снова и снова, но оно обычно отклоняется, потому что это приведет к запутанному поведению: поскольку методы экземпляра всегда выбираются перед методами расширения, это будет означать, что всеIEnumerable s обрабатываются одинаково, за исключением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); 
     } 
    } 
} 
Смежные вопросы