C# 新手:找出 foreach 块中的索引
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1192447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# newbie: find out the index in a foreach block
提问by Bab Yogoo
I have a foreach block where I want to plot out for trace-debug purposes the index of the step inside the foreach. As a C# newbie I do it as follows:
我有一个 foreach 块,我想在其中为跟踪调试目的绘制 foreach 内步骤的索引。作为 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. The reason for the numbering is just for the purpose of showing progress in the debug level and nothing else.
编辑:澄清一下,我显然熟悉 for 循环的选项,但它不是我正在经历的数组,而是一个无序的集合。编号的原因只是为了显示调试级别的进度,仅此而已。
采纳答案by Binary Worrier
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.
编辑:回应提问者的澄清。
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.
如果您要遍历没有 size 属性(例如长度或计数)的枚举器,那么您的方法将尽可能清晰。
Second Edit
Given me druthers I'd take Marc's answer using select to do this these days.
第二次编辑
给了我 druthers,我会使用 Marc 的回答来选择这些天来做到这一点。
回答by bbohac
No, there is no way to get that inside a foreach-loop. For that case you should use a for-loop or, as you mentioned, explicitly create a variable for counting.
不,没有办法在 foreach 循环中得到它。对于这种情况,您应该使用 for 循环,或者,正如您提到的,显式创建一个用于计数的变量。
回答by marc_s
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
马克
回答by MartinHN
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());
}
回答by rahul
A foreach uses the IEnumeratorinterface, which has a Current property, and MoveNext and Reset methods.
foreach 使用IEnumerator接口,该接口具有 Current 属性以及 MoveNext 和 Reset 方法。
Currentreturns the object that Enumerator is currently on, MoveNextupdates 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 而不是使用变量来跟踪它。
回答by Marc Gravell
Contrary to a few other answers, I would be perfectly happy to mix foreach
with a counter (as per the code in the question). This retains your ability to use IEnumerable[<T>]
rather than requiring an indexer.
与其他一些答案相反,我很乐意foreach
与计数器混合(根据问题中的代码)。这保留了您的使用能力,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)。
回答by Robin Day
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.
当然,如果您的列表中有重复的项目,这将不起作用。这也不是最有效的解决方案。我会坚持你原来的,只保留一个变量来跟踪索引。
回答by Paul-Jan
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). As such, you might want to consider moving boththe writeDebug and the i++ into a separate method/class (updateProgress()), and simply call that from the loop.
你的方法很清楚。但是,您可能要注意 i++ 部分实际上与循环的核心功能无关(不涉及计数/长度/其他参数)。因此,你可能要考虑移动两者的writeDebug和我++到一个单独的方法/类(的UpdateProgress()),并简单地调用从循环。
回答by Dejan Stani?
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, 德扬
回答by T. Muir
Try this:
尝试这个:
foreach (var x in y)
{
//... do something ...
WriteDebug("Step: "Array.IndexOf(y,x).ToString());
}