5

DebuggerHidden标记辅助方法非常方便,确保未处理的异常在方便的地方停止调试器:

                  在此处输入图像描述

不幸的是,这似乎不适用于迭代器块:

          在此处输入图像描述

(如果是这样,调试器将in在第二个示例中显示为当前语句)。

虽然这显然是 Visual Studio 的一个限制(我已经为此提交了一份报告),但有没有什么方法可以在仍然使用迭代器块的同时解决这个问题?

我猜这是因为编译器生成的实现迭代器的代码没有用[DebuggerHidden]. 也许有一些方法可以说服编译器这样做?

4

1 回答 1

0

也许不是您希望的答案,但作为一种解决方法,它可以获得一些分数......不确定您是否已经梦想过这一点。

有一个帮助类来解开您的迭代器,然后使用扩展方法使包装器在您的迭代器上发挥作用。我处理异常并重新抛出。在 VS2010 中,我不得不奇怪地取消选中调试选项“仅启用我的代码”以获得接近 OP 要求的行为。选中该选项仍然会使您进入实际的迭代器,但 ik 看起来像一行太远了。

这使得这个答案更像是一个实验,以证明和支持场景工作需要更好的编译器支持。

扩展方法助手类:

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 回答