Foreach and enumerable
本文关键字:enumerable and Foreach | 更新日期: 2023-09-27 18:27:44
为什么我们可以迭代项目ex
mList.ForEach((item)
{
item.xyz ....
}
对于一个简单的数组,我们需要强制foreach循环?
foreach(int i in arr)
i.xyz
或者使用委托类型?
Action<int> action = new Action<int>(myfunc);
Array.ForEach(intArray, action);
有什么不同?
第一个语法不正确。应该是这样的:
mList.ForEach(item =>
{
// item.xyz
});
ForEach
是List<T>
的一种方法,它使您能够为列表中的每个项目调用Action<T>
。
另一方面,foreach
语句为中的每个元素重复一组嵌入语句实现System.Collections.Enumerable或System.Collections.Generic.IEnumerable接口。
也就是说,ForEach
只能在列表上调用,而foreach
可以在实现IEnumerable
或IEnumerable的任何对象上调用。这就是最大的区别。
关于委托类型,没有任何区别。实际上,lambda表达式item=>{ item.xyz = ...}
是委托的简写。
该语言将foreach
定义为IEnumerable
的操作。因此,实现IEnumerable
的所有内容都是可迭代的。但是,当使用ForEach
块时,并非所有的IEnumerable
都"有意义"。
举个例子:
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);
如果编译了,它将打印出Object 0
到Object 29
,而不是Rob
30次。
原因是每次迭代枚举对象时,迭代器都会重置。对于列表上的ForEach
来说,这是有意义的,因为枚举对象已经具体化,并且不会在每次迭代时重新创建对象
为了使ForEach
在可枚举对象上工作,您还需要具体化集合(例如将其放入列表中),但即使也不总是可能,因为您可以有一个没有定义结束的可枚举对象:
public static IEnumerable<MyObject> GetObjects()
{
while(true)
yield return new MyObject { Name = "Object " };
}
在Array
上有ForEach
也是有意义的,但由于我不知道的原因,它被定义为Array.ForEach(arr)
而不是arr.ForEach()
这个故事的寓意是,如果你认为你需要一个ForEach
块,你可能想首先实现枚举,通常是List<T>
或数组(T[]
)。