13

Javaでは、このメソッドをIterator使用してhasNext、反復に(要素を消費せずに)より多くの要素があるかどうかを判断しました。つまり、 「 」メソッドhasNextのようなものです。Peek

私の質問:C#のジェネリックsを使用した「 hasNext」または「 」メソッドのようなものはありますか?PeekIEnumerator

4

6 に答える 6

36

いいえ。ただし、C#では、次の要素に移動せずに現在の要素を繰り返し要求できます。それはそれを見る別の方法です。

.NETスタイルを取得してJavaスタイルを返すC#クラスを作成するのはそれほど難しくありません。個人的には、ほとんどの場合.NETスタイルの方が使いやすいと思いますが、そこに行きます:)IEnumeratorIterator

編集:さて、これは完全にテストされていませんが、私はそれがうまくいくと思います。少なくともコンパイルします:)

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();
    }
}
于 2009-08-13T16:20:21.590 に答える
18

いいえ、残念ながらありません。

IEnumerator<T>インターフェイスは、次のメンバーのみを公開します。

方法:

Dispose
MoveNext
Reset

プロパティ

Current

于 2009-08-13T16:14:45.970 に答える
3

列挙子は遅延評価されることが多いため、HasNextはほとんど意味がありません。

于 2009-08-13T16:44:35.487 に答える
2

いいえ、ただMoveNextResetそしてCurrent

于 2009-08-13T16:20:03.197 に答える
2

このIEnumeratorおよびIEnumerator<>へのPeekの実装を確認することもできます。これは、Peek機能をIEnumeratorに追加する拡張メソッドです。それが役に立てば幸い。:)

于 2016-08-24T11:26:20.033 に答える
0

古き良き手動反復を使用する

        // 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
            {
            }
        }
于 2020-04-23T15:05:11.407 に答える