是否有一些罕见的语言构造我没有遇到过(比如我最近学到的一些,有些是关于 Stack Overflow)在 C#中得到一个表示 foreach 循环当前迭代的值?
例如,我目前根据具体情况做这样的事情:
int i = 0;
foreach (Object o in collection)
{
// ...
i++;
}
Ian Mercer 在Phil Haack 的博客上发布了类似的解决方案:
foreach (var item in Model.Select((value, i) => new { i, value }))
{
var value = item.value;
var index = item.i;
}
这将通过使用Linq 的Select
这个重载来获取 item( item.value
)及其索引( item.i
):
函数 [select Select] 的第二个参数表示源元素的索引。
new { i, value }
正在创建一个新的匿名对象 。
如果您使用的是 C#7.0 或更高版本,则可以使用ValueTuple
来避免堆分配:
foreach (var item in Model.Select((value, i) => ( value, i )))
{
var value = item.value;
var index = item.i;
}
您也可以删除该item.
通过使用自动解构:
<ol>
foreach ((MyType value, Int32 i) in Model.Select((value, i) => ( value, i )))
{
<li id="item_@i">@value</li>
}
</ol>
foreach
用于迭代实现IEnumerable
集合。它通过在集合上调用GetEnumerator
来执行此操作,该集合将返回Enumerator
。
此枚举器有一个方法和属性:
Current
返回 Enumerator Current
的对象, MoveNext
Current
更新为下一个对象。
索引的概念对于枚举的概念是陌生的,并且不能完成。
因此,大多数集合都可以使用索引器和 for 循环结构遍历。
与使用局部变量跟踪索引相比,我更倾向于在这种情况下使用 for 循环。
可以做这样的事情:
public static class ForEachExtensions
{
public static void ForEachWithIndex<T>(this IEnumerable<T> enumerable, Action<T, int> handler)
{
int idx = 0;
foreach (T item in enumerable)
handler(item, idx++);
}
}
public class Example
{
public static void Main()
{
string[] values = new[] { "foo", "bar", "baz" };
values.ForEachWithIndex((item, idx) => Console.WriteLine("{0}: {1}", idx, item));
}
}