关于c#:从foreach循环中获取当前索引

Get current index from foreach loop

本问题已经有最佳答案,请猛点这里访问。

使用C和Silverlight

如何获取列表中当前项的索引?

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
IEnumerable list = DataGridDetail.ItemsSource as IEnumerable;
List<string> lstFile = new List<string>();


foreach (var row in list)
{
  bool IsChecked = (bool)((CheckBox)DataGridDetail.Columns[0].GetCellContent(row)).IsChecked;
  if (IsChecked)
  {

    // Here I want to get the index or current row from the list                  

  }
}

如何做到这一点


你不能,因为EDCOX1的2度根本没有索引…如果你确信你的枚举小于EDCOX1,3个元素(或者EDCOX1,4),如果你使用一个EDCOX1,5个索引,你可以:

  • 不要使用FROACH,并使用EDCOX1的0个循环,将EDCOX1的2个变量转换为一般可枚举的第一个:

    1
    2
    3
    4
    5
    6
    var genericList = list.Cast<object>();
    for(int i = 0; i < genericList.Count(); ++i)
    {
       var row = genericList.ElementAt(i);
       /* .... */
    }
  • 具有外部索引:

    1
    2
    3
    4
    5
    6
    int i = 0;
    foreach(var row in list)
    {
       /* .... */
       ++i;
    }
  • 通过LINQ获取索引:

    1
    2
    3
    4
    5
    6
    foreach(var rowObject in list.Cast<object>().Select((r, i) => new {Row=r, Index=i}))
    {
      var row = rowObject.Row;
      var i = rowObject.Index;
      /* .... */    
    }
  • 在你的例子中,由于你的IEnumerable不是一个通用的,我宁愿使用带有外部索引(第二种方法)的foreach。否则,您可能希望使Cast在循环之外,将其转换为IEnumerable

    您的数据类型不清楚,但我假设object,因为它是项目源(可能是DataGridRow)…你可以不必打电话给Cast(),直接检查它是否可以转换成通用IEnumerable,但我不做这样的假设。

    所有这些都说:

    "指数"的概念与IEnumerable的概念不同。IEnumerable可能是无限的。在您的示例中,您使用的是DataGridItemsSource,因此您的IEnumerable更可能只是对象列表(或DataRows),成员数量有限(并且希望小于int.MaxValue),但IEnumerable可以表示任何可以枚举的对象(并且枚举可能永远不会结束)。

    举个例子:

    1
    2
    3
    4
    5
    6
    7
    8
    public static IEnumerable InfiniteEnumerable()
    {
      var rnd = new Random();
      while(true)
      {
        yield return rnd.Next();
      }
    }

    所以如果你这样做:

    1
    2
    3
    4
    foreach(var row in InfiniteEnumerable())
    {
      /* ... */
    }

    你的foreach将是无限的:如果你使用intlong索引,你最终会溢出它(除非你使用unchecked上下文,如果你继续添加它,它会抛出一个例外:即使你使用unchecked上下文,索引也将毫无意义…在某个时刻——当它溢出时——索引对于两个不同的值将是相同的)。

    因此,虽然给出的示例适用于典型的用法,但是如果您可以避免使用索引,那么我完全不希望使用索引。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    IEnumerable list = DataGridDetail.ItemsSource as IEnumerable;
    List<string> lstFile = new List<string>();

    int i = 0;
    foreach (var row in list)
    {
    bool IsChecked = (bool)((CheckBox)DataGridDetail.Columns[0].GetCellContent(row)).IsChecked;
    if (IsChecked)
    {
      MessageBox.show(i);
    --Here i want to get the index or current row from the list                  

    }
     ++i;
    }


    使用Enumerable。选择方法(ienumerable,func)

    1
    2
    3
    4
    5
    6
    7
    list = list.Cast<object>().Select( (v, i) => new {Value= v, Index = i});

    foreach(var row in list)
    {
        bool IsChecked = (bool)((CheckBox)DataGridDetail.Columns[0].GetCellContent(row.Value)).IsChecked;
        row.Index ...
    }

    这里有两个选项,1。使用for代替foreach进行迭代。但是在您的情况下,集合是IEnumerable,集合的上限是未知的,所以foreach将是最佳选择。所以我更喜欢使用另一个整型变量来保存迭代计数:下面是代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int i = 0; // for index
    foreach (var row in list)
    {
        bool IsChecked;// assign value to this variable
        if (IsChecked)
        {    
           // use i value here                
        }
        i++; // will increment i in each iteration
    }