web-dev-qa-db-ja.com

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                   

  }
}

これを達成する方法

9
Gopal
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;
}
6
tapos ghosh

IEnumerableにはインデックスがまったくないため、できません... enumerableが_int.MaxValue_要素より少ないことが確実な場合(またはlongインデックスを使用する場合は_long.MaxValue_)、次のことができます。

  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;
      /* .... */    
    }
    _

あなたの場合、あなたのIEnumerableは一般的なものではないので、私はむしろforeachを外部インデックスとともに使用します(2番目の方法)...そうでない場合は、_Cast<object>_ループ外で_IEnumerable<object>_に変換します。

あなたのデータタイプは質問から明確ではありませんが、アイテムソースであるためobjectであると仮定しています(DataGridRowである可能性があります)... Cast<object>()を呼び出さずに汎用_IEnumerable<object>_を使用しますが、このような仮定は行いません。


これはすべて言った:

「インデックス」の概念は、IEnumerableとは無関係です。 IEnumerableは潜在的に無限である可能性があります。あなたの例では、ItemsSourceDataGridを使用しているため、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)インデックスを使用した場合、最終的にオーバーフローします(uncheckedを使用しない限り)コンテキスト、追加し続けると例外がスローされます:uncheckedを使用した場合でも、インデックスは無意味になります...ある時点で-オーバーフローすると-インデックスは同じになります2つの異なる値)。

したがって、与えられた例は典型的な使用法で機能しますが、それを避けることができるなら、私はむしろインデックスをまったく使用したくないです。

20
Jcl

使用 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 ...
}
1
qxg

ここには2つのオプションがあります。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
}
0