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

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

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

当前回答

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

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

其他回答

c# 7最终为我们提供了一种优雅的方式:

static class Extensions
{
    public static IEnumerable<(int, T)> Enumerate<T>(
        this IEnumerable<T> input,
        int start = 0
    )
    {
        int i = start;
        foreach (var t in input)
        {
            yield return (i++, t);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var s = new string[]
        {
            "Alpha",
            "Bravo",
            "Charlie",
            "Delta"
        };

        foreach (var (i, t) in s.Enumerate())
        {
            Console.WriteLine($"{i}: {t}");
        }
    }
}

我不相信有一种方法可以获得foreach循环当前迭代的值。数数自己,似乎是最好的办法。

我能问一下,你为什么想知道?

看起来你最有可能做以下三件事中的一件:

1)从集合中获取对象,但在这种情况下,您已经拥有它。

2)为后期处理计算对象…集合有一个可以使用的Count属性。

3)根据对象在循环中的顺序设置它的属性…尽管您可以在将对象添加到集合时轻松地进行设置。

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

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

我对这个问题的解决方案是一个扩展方法WithIndex(),

http://code.google.com/p/ub-dotnet-utilities/source/browse/trunk/Src/Utilities/Extensions/EnumerableExtensions.cs

像这样使用它

var list = new List<int> { 1, 2, 3, 4, 5, 6 };    

var odd = list.WithIndex().Where(i => (i.Item & 1) == 1);
CollectionAssert.AreEqual(new[] { 0, 2, 4 }, odd.Select(i => i.Index));
CollectionAssert.AreEqual(new[] { 1, 3, 5 }, odd.Select(i => i.Item));

使用@FlySwat的答案,我想出了这个解决方案:

//var list = new List<int> { 1, 2, 3, 4, 5, 6 }; // Your sample collection

var listEnumerator = list.GetEnumerator(); // Get enumerator

for (var i = 0; listEnumerator.MoveNext() == true; i++)
{
  int currentItem = listEnumerator.Current; // Get current item.
  //Console.WriteLine("At index {0}, item is {1}", i, currentItem); // Do as you wish with i and  currentItem
}

你使用GetEnumerator来获取枚举器,然后使用for循环来进行循环。然而,诀窍是使循环的条件listEnumerator.MoveNext() == true。

由于枚举器的MoveNext方法如果存在下一个元素并且可以访问它,则返回true,因此循环条件使循环在耗尽要遍历的元素时停止。