为什么有Enumerator struct和EnumeratorImpl类?

时间:2013-09-11 14:11:37

标签: c# roslyn struct-vs-class

我正在使用Reflector查看Roslyn September 2012 CTP,我注意到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结构的性能增益,如in this answer所述,
  2. 结构没有实现IDisposable,因此不必担心这样做可能导致的错误,as noted on Eric Lippert's blog
  3. 但是,与BCL List<T>类不同,有一个嵌套的EnumeratorImpl类。是的目的是

    1. 避免使用一次性结构,
    2. 避免在明确实施的IEnumerable<SyntaxNodeOrToken>.GetEnumeratorIEnumerable.GetEnumerator方法中装箱?
    3. 还有其他原因吗?

1 个答案:

答案 0 :(得分:19)

  

还有其他原因吗?

没有想到的。您似乎已经准确地描述了序列模式这种相当奇怪的实现的目的。

我必须补充一点:Roslyn是一个不寻常的.NET应用程序,其复杂性,性能要求以及它生成的对象数量。在用户输入时,用数千个文件,数百万行和数千万个字符分析程序的编译器必须做一些非常不寻常的事情,以确保它不会淹没垃圾收集器。因此,Roslyn使用汇集策略,使用可变值类型以及其他非主流实践来帮助实现这些性能目标。我不建议承担与这些做法相关的费用和难度,除非您有经验证据确定这些做法可以缓解的严重性能问题。仅仅因为此代码是由C#编译器团队编写的,并不意味着这是您应该如何编写主流业务对象的黄金标准。