문제

수율 블록을 사용하여 구현하는 방법이 있습니까? IEnumerator<T> 뒤로 갈 수 있습니다 (MoveLast())뿐만 아니라 앞으로?

도움이 되었습니까?

해결책

반복자 블록에서 직접가 아니라.

그러나 발신자는 항상 결과를 List<T>, 또는 그냥 전화하십시오 Reverse() - 그러나 이것이 항상 적용되는 것은 아닙니다.

다른 팁

아니요, C# 컴파일러에 의해 생성 된 상태 머신이 엄격하게 앞으로 나옵니다.

많은 경우에 거꾸로가는 것조차 의미가 없습니다. 네트워크 스트림에서 반복자를 읽는 것을 상상해보십시오. 거꾸로 가려면 시간을 되 감고 네트워크에 다시 데이터를 요청할 수 없었기 때문에 읽은 모든 것을 기억해야 할 것입니다.

(약간의 손실 방식으로 데이터를 생성 한 모든 것. 각 반복에 대한 Conway의 수명을 위해 새로운 보드를 반환 한 반복자를 상상해보십시오. 이전 하나, 거꾸로 가려면 이미 돌아온 것을 다시 기억해야합니다.)

나는이 스레드가 매우 오래된 것을 알고 있지만

foreach(var item in someCollection)
{
    // Do something
}

... 다음과 같이 컴파일됩니다.

var enumerator = someCollection.GetEnumerator()
while (enumerator.MoveNext())
{
    var item = enumerator.Current;
    // Do something
}

따라서 "movenext"구문을 신경 쓰지 않으면 ienumerator를 쉽게 구현하고 "moveprevious"를 추가 할 수 있습니다. "Foreach"를 사용하는 경우 방향을 바꿀 수는 없지만 While Loop을 사용하는 경우 방향을 바꿀 수 있습니다.

또는 ... 반대 방향 (양방향이 아닌)으로 목록을 "foreach"하려면 수율 문을 활용할 수 있습니다.

public static IEnumerable<TItem> Get<TItem>(IList<TItem> list)
{
    if (list == null)
        yield break;

    for (int i = list.Count - 1; i > -1; i--)
        yield return list[i];
}

또는 ... 긴 경로로 가서 리버시를 원한다면 자신의 ienumerable/ienumerator를 구현할 수 있습니다.

public static class ReverseEnumerable
{
    public static IEnumerable<TItem> Get<TItem>(IList<TItem> list)
    {
        return new ReverseEnumerable<TItem>(list);
    }
}

public struct ReverseEnumerable<TItem> : IEnumerable<TItem>
{
    private readonly IList<TItem> _list;

    public ReverseEnumerable(IList<TItem> list)
    {
        this._list = list;
    }

    public IEnumerator<TItem> GetEnumerator()
    {
        if (this._list == null)
            return Enumerable.Empty<TItem>().GetEnumerator();

        return new ReverseEnumator<TItem>(this._list);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

public struct ReverseEnumator<TItem> : IEnumerator<TItem>
{
    private readonly IList<TItem> _list;
    private int _currentIndex;

    public ReverseEnumator(IList<TItem> list)
    {
        this._currentIndex = list.Count;
        this._list = list;
    }

    public bool MoveNext()
    {
        if (--this._currentIndex > -1)
            return true;

        return false;
    }

    public void Reset()
    {
        this._currentIndex = -1;
    }

    public void Dispose() { }

    public TItem Current
    {
        get
        {
            if (this._currentIndex < 0)
                return default(TItem);

            if (this._currentIndex >= this._list.Count)
                return default(TItem);

            return this._list[this._currentIndex];
        }
    }

    object IEnumerator.Current
    {
        get { return this.Current; }
    }
}

C5 컬렉션 라이브러리 (http://www.itu.dk/research/c5/) 거꾸로 열거 된 컬렉션 및 링크 된 목록을 구현합니다. 프로젝트는 OpenSource이므로 답변을 찾을 수 있어야합니다.

아니요. Ienumerator의 한계 중 하나는 현재 상태를 보유하고 있으며 이전 상태를 기억하지 않는다는 것입니다. 결과적으로 ienumerable은 전진합니다.

이전 상태를 유지 해야하는 경우 ienumerable을 목록이나 링크드 목록에 읽고 대신 해당 객체를 통해 열거하십시오.

실제로, 다음에 설명 된 접근법이있는 것 같습니다. 가속화 된 C# 2008. 불행히도, 두 페이지는 미리보기에서 보이지 않으며 반사에 의존해야하지만 (평소와 같이, 결과는 캐시 될 수 있음) 요점을 얻을 수 있습니다.

아니요. 사용 yield 결과 IEnumerable 단방향입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top