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

时间:2009-07-28 07:39:52

标签: c# foreach

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

int i = 1;

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

我想知道是否有办法获取当前步骤索引的值而不为此目的显式创建变量。

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

10 个答案:

答案 0 :(得分:24)

与其他一些答案相反,我非常乐意将foreach与计数器混合(根据问题中的代码)。这使您无法使用IEnumerable[<T>],而不需要索引器。

但如果你愿意,可以在LINQ:

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

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

答案 1 :(得分:22)

不,没有。

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

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

而不是每个循环

编辑:回应askers澄清。

如果你在没有大小属性​​(例如长度或数量)的枚举器中进行迭代,那么你的方法就像你能得到的一样清晰。

第二次修改
鉴于我是笨蛋,我最近会选择选择来做Marc的答案。

答案 2 :(得分:5)

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

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

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

马克

答案 3 :(得分:3)

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

答案 4 :(得分:2)

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

当前 会返回Enumerator当前所在的对象, MoveNext 将当前更新为下一个对象。< / p>

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

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

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

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

        ArrayList arrayList = new ArrayList();

        arrayList.Add("A");
        arrayList.Add("B");
        arrayList.Add("C");

        foreach (string item in arrayList)
        {
            int i = arrayList.IndexOf(item);
        }

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

答案 7 :(得分:1)

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

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

如果您将以下扩展类添加到项目中:

  public static class Extensions
  {
    public static IEnumerable<IndexValuePair<T>> WithIndex<T>(this IEnumerable<T> source)
    {
      if (source == null) throw new ArgumentNullException("source");
      var position = 0;
      foreach (T value in source)
      {
        yield return new IndexValuePair<T>(position++, value);
      }
    }
  }

  public class IndexValuePair<T>
  {
    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, 德扬

答案 8 :(得分:0)

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

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

答案 9 :(得分:0)

尝试一下:

foreach (var x in y)
{
    //... do something ...
    WriteDebug("Step: "Array.IndexOf(y,x).ToString());

}