在c#中是否有一些我没有遇到过的罕见的语言构造(比如我最近学过的一些,一些在Stack Overflow上)来获得表示foreach循环的当前迭代的值?

例如,我目前根据具体情况做这样的事情:

int i = 0;
foreach (Object o in collection)
{
    // ...
    i++;
}

当前回答

foreach用于迭代实现IEnumerable的集合。它通过在集合上调用GetEnumerator来实现这一点,该集合将返回一个Enumerator。

这个枚举器有一个方法和一个属性:

MoveNext () 当前的

Current返回Enumerator当前所在的对象,MoveNext将Current更新为下一个对象。

索引的概念与枚举的概念是不同的,不能这样做。

因此,大多数集合都可以使用索引器和for循环构造来遍历。

在这种情况下,与使用局部变量跟踪索引相比,我更喜欢使用for循环。

其他回答

最好像这样使用关键字继续安全构造

int i=-1;
foreach (Object o in collection)
{
    ++i;
    //...
    continue; //<--- safe to call, index will be increased
    //...
}

最后,c# 7有一个不错的语法,用于在foreach循环(即元组)中获取索引:

foreach (var (item, index) in collection.WithIndex())
{
    Debug.WriteLine($"{index}: {item}");
}

需要一个小扩展方法:

using System.Collections.Generic;

public static class EnumExtension {
    public static IEnumerable<(T item, int index)> WithIndex<T>(this IEnumerable<T> self)       
       => self.Select((item, index) => (item, index));
}

它只适用于List而不是任何IEnumerable,但在LINQ中有这样的:

IList<Object> collection = new List<Object> { 
    new Object(), 
    new Object(), 
    new Object(), 
    };

foreach (Object o in collection)
{
    Console.WriteLine(collection.IndexOf(o));
}

Console.ReadLine();

@Jonathan我没有说这是一个很好的答案,我只是说这只是表明,他要求的事情是可以做到的:)

@Graphain我不期望它会很快-我不完全确定它是如何工作的,它可以重复整个列表每次找到一个匹配的对象,这将是一个非常大量的比较。

也就是说,List可能保留每个对象的索引和计数。

乔纳森似乎有更好的主意,能详细说说吗?

不过,最好只是记录一下你在foreach中所做的事情,这样更简单,适应性更强。

如果集合是列表,则可以使用list。IndexOf,如:

foreach (Object o in collection)
{
    // ...
    @collection.IndexOf(o)
}

只需添加自己的索引。保持简单。

int i = -1;
foreach (var item in Collection)
{
    ++i;
    item.index = i;
}