在 foreach 循环内手动增加枚举器
我在 foreach 循环内有一个嵌套的 while 循环,我想在满足特定条件时无限期地推进枚举器。为此,我尝试将枚举器转换为 IEnumerator< T> (如果它在 foreach 循环中,则必须如此)然后在转换的对象上调用 MoveNext() ,但它给我一个错误,说我无法转换它。
无法通过引用转换、装箱转换、拆箱转换、包装转换或 null 类型转换将类型“System.DateTime”转换为 System.Collections.Generic.IEnumerator。
foreach (DateTime time in times)
{
while (condition)
{
// perform action
// move to next item
(time as IEnumerator<DateTime>).MoveNext(); // will not let me do this
}
// code to execute after while condition is met
}
手动递增的最佳方法是什么foreach 循环内的 IEnumerator?
编辑: 编辑以显示 while 循环之后有代码,一旦满足条件,我希望执行该代码,这就是为什么我想在 while 内手动递增然后打破它,而不是继续,这会让我回到顶部。如果这不可能,我相信最好的办法就是重新设计我的做法。
I have a nested while loop inside a foreach loop where I would like to advance the enumerator indefinitately while a certain condition is met. To do this I try casting the enumerator to IEnumerator< T > (which it must be if it is in a foreach loop) then calling MoveNext() on the casted object but it gives me an error saying I cannot convert it.
Cannot convert type 'System.DateTime' to System.Collections.Generic.IEnumerator via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion.
foreach (DateTime time in times)
{
while (condition)
{
// perform action
// move to next item
(time as IEnumerator<DateTime>).MoveNext(); // will not let me do this
}
// code to execute after while condition is met
}
What is the best way to manually increment the IEnumerator inside of the foreach loop?
EDIT:
Edited to show there is code after the while loop that I would like executed once the condition is met which is why I wanted to manually increment inside the while then break out of it as opposed to continue which would put me back at the top. If this isn't possible I believe the best thing is to redesign how I am doing it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
许多其他答案建议使用
继续
,这可能会很好地帮助您完成您需要做的事情。然而,为了展示手动移动枚举器,首先您必须拥有枚举器,这意味着将循环编写为while
。根据您的评论:
在循环中,
time
是一个DateTime
。它不是需要实现接口或模式才能在循环中工作的对象。times
是一系列DateTime
值,它是必须实现可枚举模式的序列。这通常通过实现IEnumerable
和IEnumerable
接口来实现,这些接口只需要T GetEnumerator()
和object GetEnumerator( )
方法。这些方法返回一个实现IEnumerator
和IEnumerator
的对象,其中定义了bool MoveNext()
方法和T 或
object Current
属性。但是time
不能转换为IEnumerator
,因为它不是这样的东西,times
序列也不是。Many of the other answers recommend using
continue
, which may very well help you do what you need to do. However, in the interests of showing manually moving the enumerator, first you must have the enumerator, and that means writing your loop as awhile
.From your comments:
In your loop,
time
is aDateTime
. It is not the object that needs to implement an interface or pattern to work in the loop.times
is a sequence ofDateTime
values, it is the one that must implement the enumerable pattern. This is generally fulfilled by implementing theIEnumerable<T>
andIEnumerable
interfaces, which simply requireT GetEnumerator()
andobject GetEnumerator()
methods. The methods return an object implementingIEnumerator<T>
andIEnumerator
, which define abool MoveNext()
method and aT
orobject Current
property. Buttime
cannot be cast toIEnumerator
, because it is no such thing, and neither is thetimes
sequence.您无法从 for 循环内部修改枚举器。语言不允许这样做。您需要使用 continue 语句才能前进到循环的下一次迭代。
但是,我不相信你的循环甚至需要继续。请继续阅读。
在代码上下文中,您需要将 while 转换为 if 以使 continue 引用 foreach 块。
但这样写很明显,以下等效变体仍然更简单
这相当于您的伪代码,因为标记为 code toexecute after while condition is met 的部分针对每个条件执行是假的。
我对所有这些的假设是针对列表中的每个项目评估条件。
You cannot modify the enumerator from inside the for loop. The language does not permit this. You need to use the continue statement in order to advance to the next iteration of a loop.
However, I'm not convinced that your loop even needs a continue. Read on.
In the context of your code you would need to convert the while to an if in order to make the continue refer to the foreach block.
But written like this it is clear that the following equivalent variant is simpler still
This is equivalent to your pseudo-code because the part marked code to execute after while condition is met is executed for each item for which condition is false.
My assumption in all of this is that condition is evaluated for each item in the list.
也许您可以使用
继续
?Perhaps you can use
continue
?您可以使用 continue 语句:
继续;
You would use the continue statement:
continue;
这只是一个猜测,但听起来您想要做的是获取日期时间列表并跳过所有满足特定条件的日期时间,然后对列表的其余部分执行操作。如果这就是您想要做的,您可能需要 System.Linq 中的 SkipWhile() 之类的东西。例如,以下代码采用一系列日期时间并跳过截止日期之前的所有日期时间;然后它打印出剩余的日期时间:
这是您想要做的事情吗?
This is just a guess, but it sounds like what you're trying to do is take a list of datetimes and move past all of them which meet a certain criteria, then perform an action on the rest of the list. If that's what you're trying to do, you probably want something like SkipWhile() from System.Linq. For example, the following code takes a series of datetimes and skips past all of them which are before the cutoff date; then it prints out the remaining datetimes:
Is that the sort of thing you're trying to do?
我绝对不会容忍我要建议的内容,但您可以在原始
IEnumerable
周围创建一个包装器,将其转换为返回可用于导航底层枚举器的项目的内容。最终结果可能如下所示。然后我们需要创建
StepWise
扩展方法。I definitely do not condone what I am about to suggest, but you can create a wrapper around the original
IEnumerable
to transform it into something that returns items which can be used to navigate the underlying the enumerator. The end result might look like the following.Then we need to create our
StepWise
extension method.您可以使用 func 作为迭代器,并保留您在该委托中更改的状态,以便在每次迭代时进行评估。
You could use a func as your iterator and keep the state that you are changing in that delegate to be evaluated each iteration.
尚未提及的一种替代方案是让枚举器返回一个包装器对象,除了被枚举的数据元素之外,该对象还允许访问其自身。例如:
想要允许在枚举期间以受控方式修改集合的数据结构也可以使用此方法(例如,通过包含“DeleteCurrentItem”、“AddBeforeCurrentItem”和“AddAfterCurrentItem”方法)。
One alternative not yet mentioned is to have an enumerator return a wrapper object which allows access to itself in addition to the data element being enumerated. For sample:
This approach could also be used by data structures that want to allow collections to be modified in controlled fashion during enumeration (e.g. by including "DeleteCurrentItem", "AddBeforeCurrentItem", and "AddAfterCurrentItem" methods).