Get current index from foreach loop

This question already has an answer here:

  • How do you get the index of the current iteration of a foreach loop? 31 answers

  • 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;
    }
    

    You can't, because IEnumerable doesn't have an index at all... if you are sure your enumerable has less than int.MaxValue elements (or long.MaxValue if you use a long index), you can:

  • Don't use foreach, and use a for loop, converting your IEnumerable to a generic enumerable first:

    var genericList = list.Cast<object>();
    for(int i = 0; i < genericList.Count(); ++i)
    {
       var row = genericList.ElementAt(i);
       /* .... */
    }
    
  • Have an external index:

    int i = 0;
    foreach(var row in list)
    {
       /* .... */
       ++i;
    }
    
  • Get the index via Linq:

    foreach(var rowObject in list.Cast<object>().Select((r, i) => new {Row=r, Index=i}))
    {
      var row = rowObject.Row;
      var i = rowObject.Index;
      /* .... */    
    }
    
  • In your case, since your IEnumerable is not a generic one, I'd rather use the foreach with external index (second method)... otherwise, you may want to make the Cast<object> outside your loop to convert it to an IEnumerable<object> .

    Your datatype is not clear from the question, but I'm assuming object since it's an items source (it could be DataGridRow )... you may want to check if it's directly convertible to a generic IEnumerable<object> without having to call Cast<object>() , but I'll make no such assumptions.


    All this said:

    The concept of an "index" is foreign to an IEnumerable . An IEnumerable can be potentially infinite. In your example, you are using the ItemsSource of a DataGrid , so more likely your IEnumerable is just a list of objects (or DataRows ), with a finite (and hopefully less than int.MaxValue ) number of members, but IEnumerable can represent anything that can be enumerated (and an enumeration can potentially never end).

    Take this example:

    public static IEnumerable InfiniteEnumerable()
    {
      var rnd = new Random();
      while(true)
      {
        yield return rnd.Next();
      }
    }
    

    So if you do:

    foreach(var row in InfiniteEnumerable())
    {
      /* ... */
    }
    

    Your foreach will be infinite: if you used an int (or long ) index, you'll eventually overflow it (and unless you use an unchecked context, it'll throw an exception if you keep adding to it: even if you used unchecked , the index would be meaningless also... at some point -when it overflows- the index will be the same for two different values).

    So, while the examples given work for a typical usage, I'd rather not use an index at all if you can avoid it.


    使用Enumerable.Select <TSource,TResult>方法(IEnumerable <TSource>,Func <TSource,Int32,TResult>)

    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 ...
    }
    
    链接地址: http://www.djcxy.com/p/52966.html

    上一篇: 在C#中获取Enumerator.Current的索引

    下一篇: 从foreach循环获取当前索引