Почему Enumerator имеет структуру и класс EnumeratorImpl?

Я смотрю на CTP- программу Roslyn в сентябре 2012 года с Reflector и заметил, что структура ChildSyntaxList имеет следующее:

public struct ChildSyntaxList : IEnumerable<SyntaxNodeOrToken>
{
    private readonly SyntaxNode node;
    private readonly int count;

    public Enumerator GetEnumerator()
    {
        return node == null ? new Enumerator() : new Enumerator(node, count);
    }

    IEnumerator<SyntaxNodeOrToken> IEnumerable<SyntaxNodeOrToken>.GetEnumerator()
    {
        return node == null
            ? SpecializedCollections.EmptyEnumerator<SyntaxNodeOrToken>()
            : new EnumeratorImpl(node, count);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return node == null
            ? SpecializedCollections.EmptyEnumerator<SyntaxNodeOrToken>()
            : new EnumeratorImpl(node, count);
    }

    public struct Enumerator
    {
        internal Enumerator(SyntaxNode node, int count)
        {
            /* logic */
        }

        public SyntaxNodeOrToken Current { get { /* logic */ } }

        public bool MoveNext()
        {
            /* logic */
        }

        public void Reset()
        {
            /* logic */
        }
    }

    private class EnumeratorImpl : IEnumerator<SyntaxNodeOrToken>
    {
        private Enumerator enumerator;

        internal EnumeratorImpl(SyntaxNode node, int count)
        {
            enumerator = new Enumerator(node, count);
        }

        public SyntaxNodeOrToken Current { get { return enumerator.Current; } }

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

        public void Dispose()
        {
        }

        public bool MoveNext()
        {
            return enumerator.MoveNext();
        }

        public void Reset()
        {
            enumerator.Reset();
        }
    }
}

То есть есть GetEnumerator метод, который возвращает структуру.

Это выглядит так

  1. использование структуры - это повышение производительности, аналогичное BCL List<T>.Enumerator структура, как отмечено в этом ответе, и что
  2. структура не реализует IDisposable чтобы не беспокоиться об ошибках, которые могут возникнуть при этом, как отмечено в блоге Эрика Липперта.

Однако в отличие от BCL List<T> класс, есть вложенный EnumeratorImpl учебный класс. Является ли целью этого

  1. избегать одноразовой конструкции, и
  2. избегать бокса внутри явно реализованного IEnumerable<SyntaxNodeOrToken>.GetEnumerator а также IEnumerable.GetEnumerator методы?

Есть ли другие причины?

1 ответ

Решение

Есть ли другие причины?

Никто не приходит на ум. Похоже, вы точно описали цели этой довольно странной реализации шаблона последовательности.

Спешу добавить: Roslyn - это необычное.NET-приложение по своей сложности, требованиям к производительности и количеству генерируемых объектов. Компилятор, который анализирует программы с тысячами файлов, миллионами строк и десятками миллионов символов, пока пользователь печатает, должен сделать довольно необычные вещи, чтобы гарантировать, что он не перегружает сборщик мусора. Поэтому Roslyn использует стратегии объединения, использует изменяемые типы значений и другие нестандартные методы для достижения этих целей производительности. Я не рекомендую брать на себя расходы и трудности, связанные с этими практиками, если у вас нет эмпирических данных, идентифицирующих серьезную проблему производительности, которую эти практики смягчают. Тот факт, что этот код был написан командой компилятора C#, не означает, что это золотой стандарт того, как вы должны писать свои основные бизнес-объекты.

Другие вопросы по тегам