2010-09-28 13 views
13

Tengo una clase con una propiedad de lista que parece perder un elemento bajo ciertas circunstancias. No puedo averiguar cuándo sucede esto.Punto de interrupción que se rompe cuando los datos cambian en un lenguaje administrado

Entonces, lo que me gustaría hacer es configurar un punto de interrupción de Visual Studio que pausará el programa en el momento en que cambie este valor. Un punto de interrupción condicional no funcionaría en este escenario, ya que no tengo idea de qué está eliminando este punto de interrupción.

Para decirlo de otra manera, quiero que mi programa se detenga en el momento en que myList.Count evalúa un nuevo número.

¿Alguna idea sobre cómo hacer esto?

Respuesta

12

Esto no es posible en C# ni en ninguno de los otros lenguajes .NET debido a limitaciones de CLR. El depurador de código nativo de Visual Studio admite puntos de interrupción de datos (link) para el código C++ que hacen exactamente esto, pero esto no es compatible con el código administrado. Puede intentar interrumpir o interceptar las llamadas al método Add y Remove en la recopilación como se sugiere en la otra respuesta a esta pregunta.

+0

Gracias. ¿Qué es el "código administrado"? – Tim

+0

Código administrado ~ = CLR/Microsoft Intermediate Language –

+0

Gracias. ¿Qué quieres decir con "~ ="? ¿Es su mano derecha una definición precisa de su lado izquierdo? Si no, ¿puedes dar una definición precisa? – Tim

2

Subclase List <t> t > con su propia clase, luego anule la cuenta (o agregue/quite) y agregue un punto de interrupción en el método que cree.

EDITAR: Como se mencionó en los comentarios, esto requeriría un gran esfuerzo ya que los métodos Agregar y Eliminar no son virtuales; una reescritura completa de los métodos sería necesaria.

Además, Colección de subclases <t> aparentemente sería una mejor solución (aunque no puedo distinguir una razón por la cual desde Agregar/Quitar no son miembros virtuales en la colección <t> tampoco;? Los comentarios).

+0

No puede anular Agregar o quitar métodos porque no son virtuales. Puede ocultar estos métodos y proporcionar nuevas versiones, pero en este caso debe cambiar todo el uso de la Lista a MyList

+1

Esto sería mucho más factible si reemplaza 'List ' con 'Collection '. – SLaks

1

Puede establecer puntos de interrupción de datos en el estudio visual, pero esto será difícil de hacer para el código administrado, ya que el recolector de basura puede mover el objeto. Dicho eso, todavía puedes lograrlo. Tendrá que habilitar la depuración nativa para su proceso. Cargue SOS en la ventana inmediata y use! DumpObject para buscar la dirección del backing store para la propiedad Count. Usando esta dirección, cree un nuevo punto de interrupción de datos con esta dirección y luego continúe y active el problema.

+0

Nunca lo he probado en lo que respecta a la depuración, pero ¿no podría pinchar el objeto para evitar que el GC lo moviera? –

1

Encuentra todos los usos para esta propiedad en particular y añade un punto de corte a todas las líneas que eliminan elementos de esta lista.

O puede crear su propia implementación de IList y establecer un punto de interrupción para Eliminar el método (no puede subclase de Lista sin cambiar todos sus clientes, porque List :: Remove no es virtual).

+0

Fui con la sugerencia "Buscar todos los usos". Esperaba una solución más fácil, pero entiendo por qué no es posible en Visual Studio. –

0

esto puede sonar demasiado complejo o no, pero puede usar el temporizador/hilo de fondo para seguir probando el valor de conteo y hacer un Debugger.Break() siempre que encuentre un valor diferente de su instancia anterior.

+0

Una idea interesante, sin embargo; no me daría los resultados que estoy buscando. Quiero saber la línea exacta que causó el cambio. –

2

Supongo que Visual Studio es IDE.

Establezca un punto de interrupción, haga clic derecho, seleccione condición, escriba myList.Count y elija Ha cambiado.

+1

"Un punto de interrupción condicional no funcionaría en este escenario, ya que no tengo idea de qué está eliminando este punto de interrupción". –

+0

Pero eso detendría la ejecución y puede inspeccionar la pila de llamadas para el delincuente. :) –

+4

Lo haría, sin embargo; Tendría que saber dónde establecer el punto de interrupción en este escenario. Creo que los puntos de interrupción condicionales son geniales y los utilizo todo el tiempo, pero en este escenario en el momento en que escribí esta pregunta, no tenía idea de qué línea de código estaba causando el problema. Aprecio tus pensamientos sobre esta pregunta sin embargo. ¡Gracias! –

1

Esto es quizás más una pregunta que una respuesta, pero puede entrar en el código de Framework al depurar, siempre que configure su Visual Studio de esa manera. Podría ser que luego puede poner el punto de interrupción en la implementación de la Lista real.

9

¿Qué tal intercambiar List<T> por ObservableCollection<T> y escuchar el evento CollectionChanged? Implementa la interfaz IList<T> por lo que debe haber suficiente superposición en los métodos disponibles para dar como resultado la sintaxis y la compatibilidad semántica.

+0

¡Esta es una gran idea! No puedo creer que no haya pensado en utilizar un ObservableCollection anteriormente. Cuando se invoca CollectionChange, ¿hay alguna manera de rastrear la pila hasta la línea de código que realizó el cambio? –

+0

@Jason: Sí, creo que sí. Dado que los eventos se generan sincrónicamente, el código que inició el cambio debería aparecer en la pila de llamadas en algún lugar ¿no? –

+0

tiene sentido para mí. Probaré esto la próxima vez que me encuentre en una situación similar. ¡Gracias! –

Cuestiones relacionadas