foreach的工作: 据我所知,
foreach是一个循环,循环遍历集合或数组 一,从0指数开始直到 该系列的最后一项。
所以,如果我在数组中有n个项目。
foreach (var item in arr)
{
}
然后,
在第一次迭代中, item = arr [0];
然后,在第二, item = arr [1];
。
。
。
在最后(第n个), item = arr [n-1];
结论:从工作开始,它似乎在每次迭代时都知道从数组中取出哪个值,或者它知道要从数组中获取的项的索引。
现在我的问题:如何在不使用新变量的情况下获取项目的索引?
foreach (string item in mylist)
{
if (item == "myitem")
{
// get index of item
break;
}
}
答案 0 :(得分:77)
这取决于你的意思“它”。迭代器知道它到达了什么索引,是的 - 在List<T>
或数组的情况下。但IEnumerator<T>
内没有一般索引。它是否在索引集合上进行迭代取决于实现。大量的集合不支持直接索引。
(事实上,foreach
并不总是使用迭代器。如果集合的编译时类型是数组,编译器将使用array[0]
,{{同样,集合可以有一个名为array[1]
的方法,该方法返回一个具有相应成员的类型,但看不到任何GetEnumerator()
/ IEnumerable
的实现。)
维护索引的选项:
IEnumerator
循环使用投影将每个项目投影到索引/值对,例如
for
使用我的SmartEnumerable
课程,这有点像上一个选项
除了第一个选项外,其他所有选项都可以使用,无论该集合是否自然编入索引。
答案 1 :(得分:18)
使用for
代替foreach
。 foreach
不公开其内部工作,它枚举任何IEnumerable
(根本不需要索引)。
for (int i=0; i<arr.Length; i++)
{
...
}
此外,如果你要做的是找到列表中特定项目的索引,则不必自己迭代它。请改用Array.IndexOf(item)
。
答案 2 :(得分:11)
您对foreach
的理解不完整。
它适用于公开IEnumerable
(或实现GetEnumerable
方法)的任何类型,并使用返回的IEnumerator
来迭代集合中的项目。
Enumerator
如何执行此操作(使用索引,yield
语句或魔术)是一个实现细节。
为了达到你想要的效果,你应该使用for
循环:
for (int i = 0; i < mylist.Count; i++)
{
}
注意:
获取列表中的项目数量会略有不同,具体取决于列表类型
For Collections: Use Count [property]
For Arrays: Use Length [property]
For IEnumerable: Use Count() [Linq method]
答案 3 :(得分:7)
如果您不想使用大量的linq并且出于某种原因不想使用for循环,那就更简单了。
int i = 0;
foreach(var x in arr)
{
//Do some stuff
i++;
}
答案 4 :(得分:2)
可能毫无意义,但是......
foreach (var item in yourList.Select((Value, Index) => new { Value, Index }))
{
Console.WriteLine("Value=" + item.Value + ", Index=" + item.Index);
}
答案 5 :(得分:1)
只有在迭代数组时才会出现这种情况;如果您正在迭代不具有索引访问概念的不同类型的集合,该怎么办?在数组的情况下,保留索引的最简单方法是简单地使用vanilla for循环。
答案 6 :(得分:1)
datas.Where((data, index) =>
{
//Your Logic
return false;
}).Any();
在一些简单的情况下,我的方法是使用where + false + any
。
它比foreach + select((data,index)=>new{data,index})
胖一点,并且没有自定义的Foreach方法。
MyLogic:
- 使用声明正文运行您的逻辑。
- 因为返回false ,所以新的可枚举数据计数为零。
- 使用 Any()让运行。
[RPlotExporter, RankColumn]
public class BenchmarkTest
{
public static IEnumerable<dynamic> TestDatas = Enumerable.Range(1, 10).Select((data, index) => $"item_no_{index}");
[Benchmark]
public static void ToArrayAndFor()
{
var datats = TestDatas.ToArray();
for (int index = 0; index < datats.Length; index++)
{
var result = $"{datats[index]}{index}";
}
}
[Benchmark]
public static void IEnumrableAndForach()
{
var index = 0;
foreach (var item in TestDatas)
{
index++;
var result = $"{item}{index}";
}
}
[Benchmark]
public static void LinqSelectForach()
{
foreach (var item in TestDatas.Select((data, index) => new { index, data }))
{
var result = $"{item.data}{item.index}";
}
}
[Benchmark]
public static void LinqSelectStatementBodyToList()
{
TestDatas.Select((data, index) =>
{
var result = $"{data}{index}";
return true;
}).ToList();
}
[Benchmark]
public static void LinqSelectStatementBodyToArray()
{
TestDatas.Select((data, index) =>
{
var result = $"{data}{index}";
return true;
}).ToArray();
}
[Benchmark]
public static void LinqWhereStatementBodyAny()
{
TestDatas.Where((data, index) =>
{
var result = $"{data}{index}";
return false;
}).Any();
}
}
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<BenchmarkTest>();
System.Console.Read();
}
}
Method | Mean | Error | StdDev | Rank |
------------------------------- |---------:|----------:|----------:|-----:|
ToArrayAndFor | 4.027 us | 0.0797 us | 0.1241 us | 4 |
IEnumrableAndForach | 3.494 us | 0.0321 us | 0.0285 us | 1 |
LinqSelectForach | 3.842 us | 0.0503 us | 0.0471 us | 3 |
LinqSelectStatementBodyToList | 3.822 us | 0.0416 us | 0.0389 us | 3 |
LinqSelectStatementBodyToArray | 3.857 us | 0.0764 us | 0.0785 us | 3 |
LinqWhereStatementBodyAny | 3.643 us | 0.0693 us | 0.0712 us | 2 |
答案 7 :(得分:0)
并非所有集合都有索引。例如,我可以使用带有Dictionary
的{{1}}(并遍历所有键和值),但我无法使用foreach
,{{1}来编写单个元素等等。
如果我确实想要遍历字典并跟踪索引,我必须使用一个单独的变量来增加自己。
答案 8 :(得分:0)
在foreach循环中迭代的序列可能不支持索引或知道这样一个概念,它只需要实现一个名为GetEnumerator的方法,该方法返回一个对象,该对象至少具有IEnumerator的接口,尽管不需要它。如果您知道迭代的内容确实支持索引并且您需要索引,那么我建议使用for
循环。
可以在foreach
中使用的示例类:
class Foo {
public iterator GetEnumerator() {
return new iterator();
}
public class iterator {
public Bar Current {
get{magic}
}
public bool MoveNext() {
incantation
}
}
}
答案 9 :(得分:0)
来自MSDN:
foreach声明重复了一个小组 每个的嵌入式语句 数组或对象中的元素 实现的集合 System.Collections.IEnumerable或 System.Collections.Generic.IEnumerable(中 T)界面。
所以,它不一定是Array。它甚至可能是一个懒惰的集合,不知道集合中的项目数。