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

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

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

当前回答

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

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

其他回答

出于兴趣,Phil Haack刚刚在Razor Templated Delegate的上下文中写了一个例子(http://haacked.com/archive/2011/04/14/a-better-razor-foreach-loop.aspx)。

实际上,他编写了一个扩展方法,将迭代包装在一个“IteratedItem”类中(见下文),允许在迭代期间访问索引和元素。

public class IndexedItem<TModel> {
  public IndexedItem(int index, TModel item) {
    Index = index;
    Item = item;
  }

  public int Index { get; private set; }
  public TModel Item { get; private set; }
}

然而,如果你在非razor环境中做一个单独的操作(例如,一个可以作为lambda提供的操作),这在非razor环境中不会是for/foreach语法的可靠替代。

字面答案——警告,性能可能不如仅使用int来跟踪索引。至少它比使用IndexOf要好。

您只需要使用Select的索引重载,用一个知道索引的匿名对象来包装集合中的每个项。这可以针对任何实现IEnumerable的对象执行。

System.Collections.IEnumerable collection = Enumerable.Range(100, 10);

foreach (var o in collection.OfType<object>().Select((x, i) => new {x, i}))
{
    Console.WriteLine("{0} {1}", o.i, o.x);
}

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

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

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

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

为什么?!

如果你使用List,最简单的方法是使用for而不是foreach:

for (int i = 0 ; i < myList.Count ; i++)
{
    // Do something...
}

或者如果你想使用foreach:

foreach (string m in myList)
{
     // Do something...
}

你可以用它来知道每个循环的索引:

myList.indexOf(m)