简体   繁体   English

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

[英]C# newbie: find out the index in a foreach block

I have a foreach block where I want to plot out for trace-debug purposes the index of the step inside the foreach. 我有一个foreach块,我想为跟踪调试目的绘制foreach内部步骤的索引。 As a C# newbie I do it as follows: 作为一个C#新手我做如下:

int i = 1;

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

I wondered if there's any way to get the value of the current step's index without explicitly creating a variable for that purpose. 我想知道是否有任何方法可以获得当前步骤索引的值而无需为此目的明确创建变量。

EDIT: To clarify, I'm obviously familiar with the option of a for loop, however it's not an array I'm going through but rather an unordered collection. 编辑:为了澄清,我显然熟悉for循环的选项,但它不是我正在经历的数组,而是一个无序的集合。 The reason for the numbering is just for the purpose of showing progress in the debug level and nothing else. 编号的原因仅仅是为了显示调试级别的进度,而不是其他任何内容。

Contrary to a few other answers, I would be perfectly happy to mix foreach with a counter (as per the code in the question). 与其他一些答案相反,我非常乐意将foreach与一个计数器混合(根据问题中的代码)。 This retains your ability to use IEnumerable[<T>] rather than requiring an indexer. 这保留了使用IEnumerable[<T>]而不需要索引器的能力。

But if you want, in LINQ: 但如果你想,在LINQ中:

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

(the counter approach in the question is a lot simpler and more effecient, but the above should map better to a few scenarios like Parallel.ForEach). (问题中的反制方法更简单,更有效,但上面应该更好地映射到一些场景,如Parallel.ForEach)。

No, there is not. 不,那里没有。

This is an instance where you're better off using a basic for loop 这是一个你最好使用基本for循环的例子

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

rather than a for each loop 而不是每个循环

EDIT : In response to askers clarification. 编辑 :回应askers的澄清。

If you're iterating through an enumerator with no size property (such as length or count), then your approach is about as clear as you can get. 如果您正在迭代没有大小属性​​(例如长度或计数)的枚举器,那么您的方法就像您可以获得的那样清晰。

Second Edit 第二次编辑
Given me druthers I'd take Marc's answer using select to do this these days. 鉴于我是druthers,这些天我会选择使用select来做Marc的答案。

No, there's no implicit "counter" inside a foreach loop, really. 不,真的,在foreach循环中没有隐含的“计数器”。

What the foreach loop does behind the covers is create an IEnumerator and then loop over the items one by one, calling the .MoveNext() method on the IEnumerator interface. foreach循环在封面后面做的是创建一个IEnumerator,然后逐个循环遍历项目,在IEnumerator接口上调用.MoveNext()方法。

There's (unfortunately?) no counter variable exposed on the IEnumerator interface - only .Reset() and .MoveNext() methods and a Current property (returning the current item) (不幸的是?)IEnumerator接口上没有暴露的计数器变量 - 只有.Reset()和.MoveNext()方法以及Current属性(返回当前项)

Marc

Your approach is about as clear as it gets. 你的方法尽可能清晰。 However, you might want to note the i++ part is not actually related to the core functionality of the loop (no count/length/other parameters involved). 但是,您可能需要注意,i ++部分实际上与循环的核心功能无关(不涉及计数/长度/其他参数)。 As such, you might want to consider moving both the writeDebug and the i++ into a separate method/class (updateProgress()), and simply call that from the loop. 因此,您可能需要考虑将writeDebug和i ++ 同时移动到单独的方法/类(updateProgress())中,并简单地从循环中调用它。

A foreach uses the IEnumerator interface, which has a Current property, and MoveNext and Reset methods. foreach使用IEnumerator接口,该接口具有Current属性,以及MoveNext和Reset方法。

Current returns the object that Enumerator is currently on, MoveNext updates Current to the next object. Current返回Enumerator 当前所在的对象, MoveNext将 Current更新为下一个对象。

There isn't a concept of index in foreach and we won't be sure of the order of enumeration. foreach中没有索引的概念,我们不确定枚举的顺序。

You will have to either apply a variable for that or use a for loop instead of that. 您必须为此应用变量或使用for循环而不是。

I would prefer use a for lop instead of tracking this using a variable. 我宁愿使用for lop而不是使用变量来跟踪它。

No, there is no way to get that inside a foreach-loop. 不,没有办法在foreach循环中得到它。 For that case you should use a for-loop or, as you mentioned, explicitly create a variable for counting. 对于这种情况,您应该使用for循环,或者如您所述,显式创建一个用于计数的变量。

It depends upon the actual type of the enumerator you are for looping over. 它取决于您要循环的枚举器的实际类型。 However, a lot of collections have the IndexOf method 但是,很多集合都有IndexOf方法

        ArrayList arrayList = new ArrayList();

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

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

Of course this doesn't work if you have duplicate items in your list. 当然,如果列表中有重复的项目,这将不起作用。 It's also not the most efficient solution. 它也不是最有效的解决方案。 I'd stick with your original one and just keep a variable to keep track of the index. 我会坚持你的原始版本,只需保留一个变量来跟踪索引。

I don't know what exactly "y" is in your example, but perhaps you could write it like this: 我不知道你的例子中究竟是什么“y”,但也许你可以像这样写:

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

Provided that you add following extension class to your project: 前提是您将以下扩展类添加到项目中:

  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, Dejan HTH,Dejan

If you absolutely need the index, go with a traditional for loop instead. 如果您绝对需要索引,请使用传统的for循环。

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

Try this: 试试这个:

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM