Язык определяет foreach
как операцию IEnumerable
. Поэтому все, что реализует IEnumerable
, является итерационным. Однако не все IEnumerable
s «имеют смысл» при использовании блока ForEach
.
Возьмите это, например:
public static IEnumerable<MyObject> GetObjects()
{
var i = 0;
while(i < 30)
yield return new MyObject { Name = "Object " + i++ };
}
И тогда вы сделать что-то вроде этого:
var objects = GetObjects();
objects.ForEach(o => o.Name = "Rob");
foreach (var obj in objects)
Console.WriteLine(obj.Name);
IF собравшего, было бы распечатать Object 0
к Object 29
- НЕ Rob
30 раз.
Причина в том, что итератор сбрасывается каждый раз, когда вы перебираете перечислимый. Имеет смысл для ForEach
в списке, поскольку перечислимое было материализовано, и объекты не воссоздаются каждый раз, когда вы его итерации.
Для того, чтобы сделать ForEach
работы над перечислимым, вы должны были бы материализовать коллекцию, а также (например, поместив его в список), но даже что не всегда возможно, так как вы можете иметь перечислимый без какой-либо определенной цели:
public static IEnumerable<MyObject> GetObjects()
{
while(true)
yield return new MyObject { Name = "Object " };
}
это также имеет смысл иметь ForEach
на Array
- но по причинам, я не знаю, он был определен как Array.ForEach(arr)
, а не arr.ForEach()
Мораль истории, если вы считаете, что вам нужен блок ForEach
, вы, вероятно, захотите материализовать перечислимое сначала, как правило, до List<T>
или массива (T[]
).
Конечно, синтакс с =>. Но вопрос в том, почему, если у меня есть int [] intArray = new int [] {2, 3, 4}; я не могу перебирать с .ForEach вместо forech (bla bla) –
Потому что 'ForEach' - это метод' List' или 'List', а 'intArray' - массив int. –
Christos