5

Roslyn September 2012 CTP with 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. この回答List<T>.Enumerator述べられているように、構造体を使用すると、BCL 構造体と同様のパフォーマンスが向上します。
  2. Eric Lippert のブログ に記載されているように、構造体は実装しないIDisposableため、そうすることで発生する可能性のあるバグを心配する必要がありません。

ただし、BCLList<T>クラスとは異なり、ネストされたEnumeratorImplクラスがあります。これの目的は

  1. 使い捨ての構造体を避ける
  2. IEnumerable<SyntaxNodeOrToken>.GetEnumerator明示的に実装されたandIEnumerable.GetEnumeratorメソッド内でのボックス化を回避しますか?

他に理由はありますか?

4

1 に答える 1

20

他に理由はありますか?

どれも思い浮かびません。このかなり奇妙なシーケンス パターンの実装の目的を正確に説明したようです。

急いで付け加えておきますが、Roslyn は、その複雑さ、パフォーマンス要件、および生成するオブジェクトの数において、並外れた .NET アプリケーションです。ユーザーが入力している間に、数千のファイル、数百万の行、数千万の文字を含むプログラムを分析するコンパイラは、ガベージ コレクターを圧倒しないようにするために、かなり珍しいことを行う必要があります。そのため、Roslyn はプーリング戦略を使用し、変更可能な値の型を使用し、その他の主流ではないプラクティスを使用して、これらのパフォーマンス目標を達成します。これらのプラクティスが軽減する深刻なパフォーマンスの問題を特定する経験的証拠がない限り、これらのプラクティスに関連する費用と困難を引き受けることはお勧めしません. このコードが C# コンパイラ チームによって作成されたからといって、これが主流のビジネス オブジェクトを作成する方法のゴールド スタンダードであるとは限りません。

于 2013-09-11T17:19:42.737 に答える