Почему 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
метод, который возвращает структуру.
Это выглядит так
- использование структуры - это повышение производительности, аналогичное BCL
List<T>.Enumerator
структура, как отмечено в этом ответе, и что - структура не реализует
IDisposable
чтобы не беспокоиться об ошибках, которые могут возникнуть при этом, как отмечено в блоге Эрика Липперта.
Однако в отличие от BCL List<T>
класс, есть вложенный EnumeratorImpl
учебный класс. Является ли целью этого
- избегать одноразовой конструкции, и
- избегать бокса внутри явно реализованного
IEnumerable<SyntaxNodeOrToken>.GetEnumerator
а такжеIEnumerable.GetEnumerator
методы?
Есть ли другие причины?
1 ответ
Есть ли другие причины?
Никто не приходит на ум. Похоже, вы точно описали цели этой довольно странной реализации шаблона последовательности.
Спешу добавить: Roslyn - это необычное.NET-приложение по своей сложности, требованиям к производительности и количеству генерируемых объектов. Компилятор, который анализирует программы с тысячами файлов, миллионами строк и десятками миллионов символов, пока пользователь печатает, должен сделать довольно необычные вещи, чтобы гарантировать, что он не перегружает сборщик мусора. Поэтому Roslyn использует стратегии объединения, использует изменяемые типы значений и другие нестандартные методы для достижения этих целей производительности. Я не рекомендую брать на себя расходы и трудности, связанные с этими практиками, если у вас нет эмпирических данных, идентифицирующих серьезную проблему производительности, которую эти практики смягчают. Тот факт, что этот код был написан командой компилятора C#, не означает, что это золотой стандарт того, как вы должны писать свои основные бизнес-объекты.