C# IEnumerator 是否有“HasNext”方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1273001/
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
Is there a "HasNext" method for an IEnumerator?
提问by JaysonFix
With Java Iterator
s, I have used the hasNext
method to determine whether an iteration has more elements (without consuming an element) -- thus, hasNext
is like a "Peek
" method.
对于 Java Iterator
s,我使用该hasNext
方法来确定迭代是否有更多元素(不消耗一个元素)——因此,hasNext
就像一个“ Peek
”方法。
My question: is there anything like a "hasNext
" or "Peek
" method with C#'s generic IEnumerator
s?
我的问题:C# 的泛型是否有类似“ hasNext
”或“ Peek
”的方法IEnumerator
?
采纳答案by Andrew Hare
No, unfortunately there isn't.
不,不幸的是没有。
The IEnumerator<T>
interface only exposes the following members:
该IEnumerator<T>
接口仅公开以下成员:
Methods:
方法:
Dispose
MoveNext
Reset
Dispose
MoveNext
Reset
Properties:
属性:
Current
Current
回答by Jon Skeet
No, but in C# you can repeatedly ask for the current element without moving to the next one. It's just a different way of looking at it.
不,但在 C# 中,您可以重复请求当前元素而无需移动到下一个元素。这只是一种不同的看待它的方式。
It wouldn't be toohard to write a C# class to take a .NET-style IEnumerator
and return a Java-style Iterator
. Personally I find the .NET style easier to use in most cases, but there we go :)
它不会是太辛苦写一个C#类采取了.NET风格IEnumerator
,并返回一个Java风格Iterator
。我个人发现 .NET 风格在大多数情况下更容易使用,但我们去了:)
EDIT: Okay, this is completely untested, but I thinkit will work. It does at least compile :)
编辑:好的,这完全未经测试,但我认为它会起作用。它至少可以编译:)
using System;
using System.Collections;
using System.Collections.Generic;
// // Mimics Java's Iterable<T> interface
public interface IIterable<T>
{
IIterator<T> Iterator();
}
// Mimics Java's Iterator interface - but
// implements IDisposable for the sake of
// parity with IEnumerator.
public interface IIterator<T> : IDisposable
{
bool HasNext { get; }
T Next();
void Remove();
}
public sealed class EnumerableAdapter<T> : IIterable<T>
{
private readonly IEnumerable<T> enumerable;
public EnumerableAdapter(IEnumerable<T> enumerable)
{
this.enumerable = enumerable;
}
public IIterator<T> Iterator()
{
return new EnumeratorAdapter<T>(enumerable.GetEnumerator());
}
}
public sealed class EnumeratorAdapter<T> : IIterator<T>
{
private readonly IEnumerator<T> enumerator;
private bool fetchedNext = false;
private bool nextAvailable = false;
private T next;
public EnumeratorAdapter(IEnumerator<T> enumerator)
{
this.enumerator = enumerator;
}
public bool HasNext
{
get
{
CheckNext();
return nextAvailable;
}
}
public T Next()
{
CheckNext();
if (!nextAvailable)
{
throw new InvalidOperationException();
}
fetchedNext = false; // We've consumed this now
return next;
}
void CheckNext()
{
if (!fetchedNext)
{
nextAvailable = enumerator.MoveNext();
if (nextAvailable)
{
next = enumerator.Current;
}
fetchedNext = true;
}
}
public void Remove()
{
throw new NotSupportedException();
}
public void Dispose()
{
enumerator.Dispose();
}
}
public sealed class IterableAdapter<T> : IEnumerable<T>
{
private readonly IIterable<T> iterable;
public IterableAdapter(IIterable<T> iterable)
{
this.iterable = iterable;
}
public IEnumerator<T> GetEnumerator()
{
return new IteratorAdapter<T>(iterable.Iterator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public sealed class IteratorAdapter<T> : IEnumerator<T>
{
private readonly IIterator<T> iterator;
private bool gotCurrent = false;
private T current;
public IteratorAdapter(IIterator<T> iterator)
{
this.iterator = iterator;
}
public T Current
{
get
{
if (!gotCurrent)
{
throw new InvalidOperationException();
}
return current;
}
}
object IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
gotCurrent = iterator.HasNext;
if (gotCurrent)
{
current = iterator.Next();
}
return gotCurrent;
}
public void Reset()
{
throw new NotSupportedException();
}
public void Dispose()
{
iterator.Dispose();
}
}
回答by Ray
Enumerators are often lazily evaluated so HasNext makes little sense.
枚举器经常被懒惰地评估,所以 HasNext 没有什么意义。
回答by Bryida
You can also try having a look at this Implementing Peek to IEnumerator and IEnumerator<>. It's an extension method that adds the Peek functionality to IEnumerator. Hope it helps. :)
您还可以尝试查看此对 IEnumerator 和 IEnumerator<> 的实现查看。它是一种向 IEnumerator 添加 Peek 功能的扩展方法。希望能帮助到你。:)
回答by Phil
Use good old manual iteration
使用好的旧手动迭代
// IEnumerable<>
for (int i = 0; i < enumerable.Count(); i++)
{
var item = enumerable.ElementAt(i);
if(i + 1 < enumerable.Count()) // eq. Iterator.HasNext
{
}
}
// IList<>
for (int i = 0; i < list.Count; i++)
{
var item = list[1];
if (i + 1 < list.Count) // eq. Iterator.HasNext
{
}
}