C#newbie:找出foreach块中的索引

我有一个foreach块,我想为跟踪调试目的绘制foreach内部步骤的索引。 作为一个C#新手我做如下:

int i = 1; foreach (x in y) { ... do something ... WriteDebug("Step: "+i.ToString()); i++; } 

我想知道是否有任何方法可以获得当前步骤索引的值而无需为此目的明确创建变量。

编辑:为了澄清,我显然熟悉for循环的选项,但它不是我正在经历的数组,而是一个无序的集合。 编号的原因仅仅是为了显示调试级别的进度而不是其他任何内容。

不,那里没有。

这是一个你最好使用基本for循环的例子

 for(int i = 0; i < y.Count; i++) { } 

而不是每个循环

编辑 :回应askers的澄清。

如果您在没有大小属性​​(例如长度或计数)的枚举器中进行迭代,那么您的方法就像您可以获得的那样清晰。

第二次编辑
鉴于我是钻孔机,我会选择这样做以取得Marc的答案。

与其他一些答案相反,我非常乐意将foreach与一个计数器混合(根据问题中的代码)。 这保留了使用IEnumerable[]而不需要索引器的能力。

但如果你想,在LINQ:

  foreach (var pair in y.Select((x,i) => new {Index = i,Value=x})) { Console.WriteLine(pair.Index + ": " + pair.Value); } 

(问题中的反制方法更简单,更有效,但上面应该更好地映射到一些场景,如Parallel.ForEach)。

不,真的,在foreach循环中没有隐含的“计数器”。

foreach循环在封面后面做的是创建一个IEnumerator,然后逐个循环遍历项目,在IEnumerator接口上调用.MoveNext()方法。

(不幸的是?)没有在IEnumerator接口上公开的计数器变量 – 只有.Reset()和.MoveNext()方法和一个Current属性(返回当前项)

你的方法尽可能清晰。 但是,您可能需要注意,i ++部分实际上与循环的核心function无关(不涉及计数/长度/其他参数)。 因此,您可能需要考虑将writeDebug和i ++移动到单独的方法/类(updateProgress())中,并简单地从循环中调用它。

foreach使用IEnumerator接口,该接口具有Current属性以及MoveNext和Reset方法。

Current返回Enumerator 当前所在的对象, MoveNext将 Current更新为下一个对象。

foreach中没有索引的概念,我们不确定枚举的顺序。

您必须为此应用变量或使用for循环而不是。

我更喜欢使用for lop而不是使用变量来跟踪它。

不,没有办法在foreach循环中得到它。 对于这种情况,您应该使用for循环,或者,如您所述,显式创建一个用于计数的变量。

它取决于您要循环的枚举器的实际类型。 但是,很多集合都有IndexOf方法

  ArrayList arrayList = new ArrayList(); arrayList.Add("A"); arrayList.Add("B"); arrayList.Add("C"); foreach (string item in arrayList) { int i = arrayList.IndexOf(item); } 

当然,如果列表中有重复的项目,这将不起作用。 它也不是最有效的解决方案。 我会坚持你原来的,只需保留一个变量来跟踪索引。

我不知道你的例子中究竟是什么“y”,但也许你可以像这样写:

  foreach (var x in y.WithIndex()) { WriteDebug(String.Format("Step: {0}", x.Index)); } 

前提是您将以下扩展类添加到项目中:

  public static class Extensions { public static IEnumerable> WithIndex(this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); var position = 0; foreach (T value in source) { yield return new IndexValuePair(position++, value); } } } public class IndexValuePair { public IndexValuePair(Int32 index, T value) { this.index = index; this.value = value; } private readonly Int32 index; public Int32 Index { get { return index; } } private readonly T value; public T Value { get { return value; } } } 

HTH,Dejan

如果您绝对需要索引,请使用传统的for循环。

 for (int i = 0; i < y.Count; i++) { WriteDebug("Step: "+i.ToString()); }