Gibt es eine „hasNext“ Verfahren für einen IEnumerator?
-
13-09-2019 - |
Frage
Mit Java Iterator
s ich die hasNext
Methode verwendet habe, um zu bestimmen, ob eine Wiederholung mehr Elemente hat (ohne ein Element raubend.) - so hasNext
ist wie eine „Peek
“ Methode
Meine Frage: Gibt es so etwas wie ein "hasNext
" oder "Peek
" Methode mit C # 's allgemeinen IEnumerator
s
Lösung
Nein, leider gibt es nicht.
Die IEnumerator<T>
Schnittstelle nur macht folgende Elemente:
Methoden:
Dispose
MoveNext
Reset
Eigenschaften :
Current
Andere Tipps
Nein, aber in C # können Sie immer wieder für das aktuelle Element stellen, ohne auf den nächsten zu bewegen. Es ist nur eine andere Art und Weise, es zu betrachten.
Es wäre nicht zu schwer, eine C # Klasse zu schreiben, um einen .NET-Stil IEnumerator
zu nehmen und eine Java-Stil Iterator
zurückzukehren. Persönlich finde ich die .NET-Stil leichter in den meisten Fällen zu verwenden, aber es gehen wir:)
EDIT: Okay, das ist völlig ungetestet, aber ich denkt es wird funktionieren. Es ist zumindest kompilieren:)
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();
}
}
Enumeratoren werden oft träge ausgewertet, so hasNext wenig Sinn macht.
Nope , nur MoveNext
, Reset
und Current
.
Sie können auch versuchen, einen Blick auf diese Implementierung Peek mit zu IEnumerator und IEnumerator <> . Es ist eine Erweiterung Methode, die Peek-Funktionalität IEnumerator hinzufügt. Ich hoffe es hilft. :)