从foreach循环获取当前索引

时间:2016-04-27 06:33:09

标签: c# silverlight for-loop foreach

使用C#和Silverlight

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

代码:

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                   

  }
}

如何实现这个

4 个答案:

答案 0 :(得分:19)

您不能,因为IEnumerable根本没有索引... 如果您确定您的可枚举元素少于int.MaxValue (或long.MaxValue如果您使用long索引),您可以:

  1. 请勿使用foreach,并使用for循环,首先将IEnumerable转换为通用枚举:

    var genericList = list.Cast<object>();
    for(int i = 0; i < genericList.Count(); ++i)
    {
       var row = genericList.ElementAt(i);
       /* .... */
    }
    
  2. 有一个外部索引:

    int i = 0;
    foreach(var row in list)
    {
       /* .... */
       ++i;
    }
    
  3. 通过Linq获取索引:

    foreach(var rowObject in list.Cast<object>().Select((r, i) => new {Row=r, Index=i}))
    {
      var row = rowObject.Row;
      var i = rowObject.Index;
      /* .... */    
    }
    
  4. 在您的情况下,由于您的IEnumerable不是通用的,我宁愿将foreach与外部索引(第二种方法)一起使用...否则,您可能想要{在您的循环外部{1}}将其转换为Cast<object>

    您的数据类型在问题中不明确,但我假设IEnumerable<object>,因为它是项目来源(可能是object)...您可能想要检查它是否可以直接转换为通用DataGridRow,无需致电IEnumerable<object>,但我不会做出这样的假设。

    所有这些都说:

    “索引”的概念对Cast<object>()来说是陌生的。 IEnumerable可能是无限的。在您的示例中,您使用的是IEnumerable的{​​{1}},因此您的ItemsSource更有可能只是一个对象列表(或DataGrid),且有限(和{希望小于IEnumerable个成员数,但DataRows可以表示任何可以枚举的内容(并且枚举可能永远不会结束)。

    举个例子:

    int.MaxValue

    所以,如果你这样做:

    IEnumerable

    您的public static IEnumerable InfiniteEnumerable() { var rnd = new Random(); while(true) { yield return rnd.Next(); } } 将是无限的:如果您使用foreach(var row in InfiniteEnumerable()) { /* ... */ } (或foreach)索引,您最终会将其溢出(除非您使用int上下文如果你继续添加它会抛出一个异常:即使你使用了long,索引也没有意义......在某些时候 - 当它溢出时 - 索引对于两个不同的是相同的值)。

    因此,虽然给出的示例适用于典型用法,但如果可以避免使用,我宁愿不使用索引。

答案 1 :(得分:5)

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

答案 2 :(得分:1)

使用Enumerable.Select<TSource, TResult> Method (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 ...
}

答案 3 :(得分:0)

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

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
}