5

DebuggerHidden очень удобно для маркировки вспомогательных методов, убедившись, необработанное исключение остановки отладчика в удобном месте:Как объединить DebuggerHidden с методами блока итератора?

                  enter image description here

К сожалению, это не похоже на работу с блоки итераторов:

          enter image description here

(если бы это было так, отладчик покажет in в качестве текущего оператора во втором примере).

Хотя это, очевидно, ограничение Visual Studio (для которого у меня есть submitted a report), есть ли способ, которым я мог бы обойти эту проблему, продолжая использовать блок итератора?

Я предполагаю, что это происходит потому, что код сгенерированного компилятором для реализации итератора не помечен [DebuggerHidden]. Возможно, есть какой-то способ убедить компилятор сделать это?

+0

Я не очень понимаю ваше дизайнерское решение скрывающихся исключений таким образом. Я вижу две ситуации, которые могут произойти: 1) Вы пишете библиотеку, которая будет использоваться другими разработчиками. В этом случае у них нет источников, а в VS наименьший уровень видимого стека будет ThrowIterator. Так вы и хотели в первую очередь. 2) Этот код используется только вашей командой, внутри, для вашего проекта. В этом случае, почему вы позволили бы неперехватываемое исключение, подобное этому, и не обрабатывали его? В случае его броска, даже при отладке, вы действительно хотите видеть, что он находится внутри ThrowIterator, и большинство imp –

+0

Несомненно, не имеет значения, почему я использую эту функцию. Он есть, и я просто хочу посмотреть, как заставить его работать при любых обстоятельствах. –

+0

Но если вам интересно, рассмотрите метод 'PerformQuery', который выдает, если аргументы не имеют смысла. Он используется только нашей командой.Исключением является неотображение, потому что это отладочная сборка, которая * специально избегает * улавливания исключений * просто *, так что Visual Studio останавливается в нужном месте. Если проект просто закрыт с общим сообщением «было проблемой», разве это не сделало бы отладку излишне сложнее? Мы знаем, что есть ошибка, возможно, остановка точно на правильной линии! –

ответ

0

Возможно, это не тот ответ, на который вы надеялись, но в качестве обходного пути он может набрать несколько очков ... не уверен, что вы уже мечтали об этом.

Имейте вспомогательный класс, который разворачивает ваш итератор, а затем использует метод расширения для приведения обертки в игру на вашем итераторе. Я обрабатываю исключения и ретроу. В VS2010 мне пришлось странно отключить опцию debug «Enable just my code», чтобы получить поведение, близкое к тому, что запросил OP. Оставляя выбранную опцию, вы по-прежнему бросаете вас в фактический итератор, но ik выглядит как одна строка слишком далеко.

Это делает этот ответ скорее экспериментом, чтобы доказать и подкрепить, что для работы сценария необходима лучшая поддержка компилятора.

Extension метод вспомогательный класс:

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

Wrapper:

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); 
      } 
     } 
+0

Кажется, не работает так, как я описал в вопросе :(Кроме того, ваш пример использования вообще не бросается вообще, с или без «Скрыть». –

+0

Да, он способен выбрать стек из кадра кусок кода, который уже выполнен ... пробная версия/ошибка началась ... – rene

Смежные вопросы