2015-12-22 2 views
-2

Почему мы можем перебирать вещь эксForeach и перечислим

mList.ForEach((item) 
{ 
    item.xyz .... 
} 

и для простого массива, мы должны заставить Еогеасп цикла?

foreach(int i in arr) 
    i.xyz 

или использовать тип делегата?

Action<int> action = new Action<int>(myfunc); 
Array.ForEach(intArray, action); 

В чем разница?

ответ

2

Язык определяет 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[]).

4

Неправильный первый синтаксис. Это должно быть так:

mList.ForEach(item => 
{ 
    // item.xyz 
}); 

ForEach является метод List<T>, что позволяет для каждого элемента в списке, чтобы вызвать Action<T>.

С другой стороны оператор foreach

повторяет группу внедренными утверждений для каждого элемента в массив или объект коллекции, который реализует System.Collections.IEnumerable или System.Collections.Generic .Inumerable интерфейс.

Это, как говорится, ForEach можно назвать только по спискам и foreach можно назвать любой объект, который реализует либо IEnumerable или IEnumerable. Здесь большая разница.

Относительно типа делегата нет никакой разницы. Фактически, лямбда-выражения item=>{ item.xyz = ...} являются сокращением для делегатов.

+0

Конечно, синтакс с =>. Но вопрос в том, почему, если у меня есть int [] intArray = new int [] {2, 3, 4}; я не могу перебирать с .ForEach вместо forech (bla bla) –

+1

Потому что 'ForEach' - это метод' List' или 'List ', а 'intArray' - массив int. – Christos

Смежные вопросы