5

DebuggerHiddenヘルパーメソッドをマークするのに非常に便利で、未処理の例外がデバッガーを便利な場所で停止することを確認します。

                  ここに画像の説明を入力してください

残念ながら、これはイテレータブロックでは機能しないようです。

          ここに画像の説明を入力してください

(もしそうなら、デバッガーはin2番目の例の現在のステートメントとしてを表示します)。

これは明らかにVisualStudio(レポートを提出した)の制限ですが、イテレーターブロックを使用しながら、この問題を回避できる方法はありますか?

これは、イテレータを実装するためにコンパイラが生成したコードがでマークされていないために発生すると推測しています[DebuggerHidden]。おそらく、コンパイラにそうするように説得する方法はありますか?

4

1 に答える 1

0

あなたが望んでいた答えではないかもしれませんが、回避策として、いくつかのポイントを得ることができます...あなたがすでにこれを夢見ていたかどうかはわかりません.

イテレータをアンラップするヘルパー クラスを作成し、拡張メソッドを使用してイテレータでラッパーを実行します。例外を処理して再スローします。VS2010では、OPが要求したものに近い動作を得るために、奇妙なことに「コードだけを有効にする」デバッグオプションのチェックを外す必要がありました。オプションをチェックしたままにすると、実際のイテレータにドロップされますが、 ik は 1 行が多すぎるように見えます。

これにより、この回答は、シナリオが機能するためにはより優れたコンパイラ サポートが必要であることを証明し、裏付けるためのより多くの実験になります。

拡張メソッド ヘルパー クラス:

public static class HiddenHelper
{
    public static HiddenEnumerator<T> Hide<T>(this IEnumerable<T> enu )
    {
        return HiddenEnumerator<T>.Enumerable(enu);
    }
}

ラッパー:

public class HiddenEnumerator<T> : IEnumerable<T>, IEnumerator<T>
    {
        IEnumerator<T> _actual;
        private HiddenEnumerator(IEnumerable<T> enu)
        {
            _actual = enu.GetEnumerator();
        }

        public static HiddenEnumerator<T> Enumerable(IEnumerable<T> enu )
        {
            return new HiddenEnumerator<T>(enu);
        }

        public T Current
        {
            [DebuggerHidden]
            get 
            { 
                T someThing = default(T);
                try
                {
                   someThing = _actual.Current;
                }
                catch
                {
                   throw new Exception();
                }
                return someThing; 
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return this;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        public void Dispose()
        {
            _actual.Dispose();
        }

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

        [DebuggerHidden]
        public bool MoveNext()
        {
                bool move = false;
                try
                {
                    move = _actual.MoveNext();
                }
                catch
                {
                     throw new IndexOutOfRangeException();
                }
               return move;
        }

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

使用法:

        public IEnumerable<int> Power(int number, int exponent)
        {
            int counter = 0;
            int result = 1;
            while (counter++ < exponent)
            {
                if (result>Int16.MaxValue) throw new Exception();
                result = result * number;
                yield return result;
            }
        }

        public void UseIt()
        {
            foreach(var i in Power(Int32.MaxValue-1,5).Hide())
            {
                Debug.WriteLine(i);
            }
        }
于 2012-08-17T07:43:17.313 に答える