从foreach循环中获取当前索引[重复]
Posted
技术标签:
【中文标题】从foreach循环中获取当前索引[重复]【英文标题】:Get current index from foreach loop [duplicate] 【发布时间】:2016-08-21 07:01:08 【问题描述】:使用 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
如何做到这一点
【问题讨论】:
【参考方案1】:你不能,因为IEnumerable
根本没有索引... 如果你确定你的可枚举元素少于int.MaxValue
元素 (或@987654324 @如果你使用long
索引),你可以:
不要使用 foreach,而是使用 for
循环,首先将您的 IEnumerable
转换为通用枚举:
var genericList = list.Cast<object>();
for(int i = 0; i < genericList.Count(); ++i)
var row = genericList.ElementAt(i);
/* .... */
有一个外部索引:
int i = 0;
foreach(var row in list)
/* .... */
++i;
通过 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
与外部索引(第二种方法)一起使用...否则,您可能希望将 Cast<object>
放在您的外部循环将其转换为IEnumerable<object>
。
问题中您的数据类型不清楚,但我假设 object
因为它是项目源(可能是 DataGridRow
)...您可能想检查它是否可以直接转换为通用 @987654337 @而不必打电话给Cast<object>()
,但我不会做这样的假设。
这一切都说了:
“索引”的概念对于 IEnumerable
来说是陌生的。 IEnumerable
可能是无限的。在您的示例中,您使用的是DataGrid
的ItemsSource
,因此您的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
,索引也将毫无意义......在某些时候 - 当它溢出时 - 对于两个不同的值,索引将是相同的)。
因此,虽然给出的示例适用于典型用法,但如果可以避免的话,我宁愿不使用索引。
【讨论】:
选项 3 非常棒。我喜欢它! @pnizzle 这不是最优的,因为它循环列表两次... @cvbattum 不,它没有......是什么让你认为它循环了两次? (编辑:我只是tested it,它绝对不会循环两次)【参考方案2】: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;
【讨论】:
如果您可以使用for
,我看不出使用foreach
的意义...:P【参考方案3】:
使用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 ...
【讨论】:
【参考方案4】:您在这里有两个选择,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
【讨论】:
以上是关于从foreach循环中获取当前索引[重复]的主要内容,如果未能解决你的问题,请参考以下文章