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.
My question: is there anything like a "hasNext
" or "Peek
" method with C#'s generic IEnumerator
s?
boolean hasNext(): It returns true if Iterator has more element to iterate. Object next(): It returns the next element in the collection until the hasNext()method return true. This method throws 'NoSuchElementException' if there is no next element.
hasNext will check to see if calling next will actually return an item. Good for indicating when we've reached the end of a collection. rewind will reset the index to zero so we can loop over the collection again. current will return the current item at the index without advancing the index.
The IEnumerator interface is used to fetch the current element from a collection. It contains a property called Current. Apart from a property, it also contains two methods, namely: MoveNext and Reset.
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.
It wouldn't be too hard 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 :)
EDIT: Okay, this is completely untested, but I think it 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();
}
}
No, unfortunately there isn't.
The IEnumerator<T>
interface only exposes the following members:
Methods:
Dispose
MoveNext
Reset
Properties:
Current
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With