2010-08-18 7 views
5

¿Hay alguna manera de obtener el depurador de Visual Studio para mostrar el contenido de una expresión F # seq?Mostrar una secuencia en la ventana del reloj

Visual Studio conoce los objetos IEnumerable<T> y le da una vista de resultados dentro de la ventana del reloj. Si miras uno de estos en la ventana del reloj, obtienes un desorden de campos privados.

Algunas alternativas posibles:

  • fsi.exe hace un buen trabajo de secuencias de impresión, pero no interactúa con el depurador
  • Encontrar una manera de llamar Seq.toArray desde el interior del depurador. No puedo encontrar la sintaxis correcta para invocar esto desde, digamos, la ventana Inmediato.
  • Escriba un vizualizador. No sé si es posible adjuntar vizualizadores a los tipos de Microsoft.
  • ¿Algo más ...?

Editar: La posterior investigación revela que los objetos seq F # 's implementan IEnumerable<T> bien - que aparecen en la ventana de inspección como tal - pero por alguna razón no aparece la vista de resultados.

Sin embargo, los objetos F # seq no parecen ser simples IEnumerables; en cambio, parecen ser cierres provenientes de las funciones dentro del módulo Seq. (F # seq objetos parecen ser instancias creadas utilizando { new IEnumerable with ... }.)

+0

lástima LINQ no es compatible con ventanas del depurador: http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows. aspx –

+0

ver mi respuesta sobre cómo hacer que aparezca el nodo Resultados – JaredPar

Respuesta

8

Una forma de hacer esto es utilizar el nodo Results vista que se añadió en Visual Studio 2008. Si el sistema. Core.dll se carga en el proceso, cualquier tipo que implemente IEnumerable<T> obtendrá un nodo adicional cuando se expanda con el nombre Results. Al expandir ese nodo, se enumerará el IEnumerable<T> y se mostrarán los resultados.

El tipo F # seq es solo un alias para IEnumerable<T> por lo que obtiene el mismo beneficio.

results view

Por defecto que no ven esto en C#, ya que no hace uso de ningún tipo en System.Core. Pero puede forzar esta DLL en el proceso con la siguiente línea.

// Force System.Core into the process 
let x = typeof<System.Linq.Enumerable> 
+0

Solo por curiosidad, ¿qué sucede cuando un IEnumerable es una lista infinita? – Gabe

+2

Eso es brillante. No necesita modificar su código. Funciona si escribe esto en la ventana inmediata: 'System.Reflection.Assembly.Load (" System.Core, Version = 3.5.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089, processorArchitecture = MSIL ")' –

+0

@Gabe, At ese punto que expande la vista de resultados esencialmente se suspenderá hasta que se agote el tiempo de espera para la llamada al depurador (suponiendo que IEnumerable es un código administrado al 100%). Si es nativo, puede terminar con un desbordamiento de pila, un punto muerto, sin memoria ... Estas son las razones por las que la vista de resultados no se expande en línea de forma predeterminada. – JaredPar

2

Puede forzar la evaluación colocando el seq en una lista. Suponiendo q es un seq<int>, esto funciona en la ventana de inspección:

new System.Collections.Generic.List<int>(q)

Por cierto: seq es un alias para IEnumerable. Como se define en prim-types.fsi:

/// <summary>An abbreviation for the CLI type <c>System.Collections.Generic.IEnumerable&lt;_&gt;</c></summary> 
type seq<'T> = IEnumerable<'T> 
+0

¡Verboso, pero funciona! Gracias. –

2

Bueno, la razón por la que aparecen como el cierre se debe a que es lo que son: ss no se evalúan hasta que realmente se utilicen en el código. Puedes tener un seq infinito, y eso llevaría mucho tiempo mostrarlo en el depurador. Y dado que no es imposible que la evaluación tenga algún efecto secundario, evaluarlos correctamente, la creación puede causar un problema que se muestre solo en el depurador o en el código real, pero no en ambos.

Si sabe que no hay problema con la evaluación, puede ponerlo en una lista u otra colección que no se evalúe perezosamente y luego verificar si es correcto aquí.

+0

Pero un IEnumerable simple, en cualquier otro lenguaje .NET, también es perezoso. Es por eso que, cuando tienes una secuencia C#, Visual Studio te hace abrir la vista de resultados a mano. No estoy seguro de por qué F # necesita cierres aquí. –

+0

Bueno, si leo esta pregunta correctamente http://stackoverflow.com/questions/2049806/debugging-an-ienumerable-method, Lazy IEnumerable no debería mostrar tampoco. Mi suposición en este punto es que el depurador es lo suficientemente inteligente como para detectar cuándo un IEnumerable no es evaluado de forma diferida (si es, por ejemplo, una lista) y luego mostrarlo en el depurador. –

3

entorno de prueba:

let get s = 
    for x in s do // breakpoint is set here 
     printfn "%A" s 

get <| seq {for i in 1..10 -> i} 

Esto debería hacer el trabajo en la ventana Inspección rápida:

Microsoft.FSharp.Collections.SeqModule.ToArray(s) 

o puede agregar esta línea para asegurarse de que se carga System.Core (y System.Linq.Enumerable es accesible)

let s : System.Linq.Expressions.Expression = Unchecked.defaultof<_> 

después de que se puede utilizar esta sintaxis en Inspección rápida

System.Linq.Enumerable.ToList(s) 
Cuestiones relacionadas