2012-06-15 14 views
5

DebuggerHidden es bastante práctico para el marcado de los métodos de ayuda, asegurándose de que las excepciones no controladas detienen el depurador en un lugar conveniente:¿Cómo combinar DebuggerHidden con métodos de bloques de iteradores?

                  enter image description here

Desafortunadamente, esto no parece trabajar con bloques de iterador:

          enter image description here

(si lo hiciera, el depurador mostraría in como la instrucción actual en el segundo ejemplo).

Si bien esto es obviamente una limitación de Visual Studio (para el que tengo submitted a report), ¿hay alguna manera de que pueda evitar este problema mientras sigo usando un bloque de iterador?

Supongo que esto sucede porque el código generado por el compilador para implementar el iterador no está marcado con [DebuggerHidden]. Tal vez haya alguna forma de convencer al compilador para que haga eso.

+0

Realmente no entiendo su decisión de diseño de las excepciones que ocultan esta manera. Puedo ver dos situaciones que pueden ocurrir: 1) Está escribiendo una biblioteca para ser utilizada por otros desarrolladores. En este caso, no tienen sus fuentes y en VS el nivel de pila visible más bajo será ThrowIterator. Entonces es lo que querías en primer lugar. 2) Este código es utilizado solo por su equipo, internamente, para su proyecto. En este caso, ¿por qué dejarías que una excepción no detectada se deslizara así y no la manejara? En caso de que se produzca, incluso cuando se está depurando, en realidad quieres ver que está dentro de ThrowIterator, y la mayoría imp –

+0

Seguramente no importa por qué estoy usando esta función. Está ahí y solo quiero ver cómo hacerlo funcionar en cualquier circunstancia. –

+0

Pero si tiene curiosidad, considere un método 'PerformQuery', que se lanza si los argumentos no tienen sentido. Solo nuestro equipo lo usa internamente.La excepción no se detecta porque es una compilación de depuración, que * evita específicamente * capturar excepciones * solo * para que Visual Studio se detenga exactamente en el lugar correcto. Si el proyecto acaba de cerrarse con un mensaje genérico de "hubo un problema", ¿no sería eso lo único que haría innecesariamente la depuración? * Sabemos * que hay un error, ¡podría detenerse exactamente en la línea correcta! –

Respuesta

0

Quizás no sea la respuesta que esperaba, pero como solución alternativa podría obtener algunos puntos ... no estoy seguro de si ya lo había soñado.

Tiene una clase de ayuda que desenvuelve su iterador y luego usa un método de extensión para poner el envoltorio en juego en su iterador. Manejo de excepciones y vuelvo a lanzar. En VS2010 tuve que desmarcar de forma extraña la opción de depuración 'Habilitar solo mi código' para obtener un comportamiento cercano a lo que OP pedía. Dejar la opción marcada aún te deja en el iterador real, pero ik parece una línea demasiado lejos.

Eso hace que esta respuesta sea más un experimento para probar y respaldar que se necesita una mejor compatibilidad del compilador para que el escenario funcione.

extensión de clase método de ayuda:

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

Envoltura:

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(); 
     } 
    } 

Uso:

 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

Parece que no funciona de la forma en que lo describí en la pregunta :(Además, su ejemplo de "uso" en realidad no arroja nada, con o sin 'Ocultar '. –

+0

Sí, es capaz de elegir una pila de una pieza de código que ya se ejecutó ... prueba/error comenzó ... – rene

Cuestiones relacionadas