2010-08-18 57 views
5

有什么办法让Visual Studio调试器显示F#seq表达式的内容?在观察窗口中显示一个顺序

Visual Studio知道约IEnumerable<T>对象,并为您提供观察窗口内的结果视图。如果你在观察窗口看到其中的一个,你会看到一堆私人领域。

一些潜在的替代品:

  • fsi.exe做印刷序列的一个不错的工作,但它不与调试
  • 互动找到一个方法来调用Seq.toArray从调试器内。我无法从即时窗口找到正确的语法来调用它。
  • 写一个vizualiser。我不知道是否可以将vizualisers附加到Microsoft类型。
  • 别的东西......?

编辑:进一步的调查表明,F#的seq对象实现IEnumerable<T>就好了 - 它们出现在监视窗口中这样 - 但由于某些原因,结果视图不会出现。

但是,F# seq对象似乎不是普通的IEnumerables;相反,它们看起来是来自 Seq模块内功能的关闭。 (F#seq对象看起来是使用{ new IEnumerable with ... }创建的实例。)

+0

太差LINQ是不支持在调试器窗口:http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows。 aspx – 2010-08-18 13:29:45

+0

看到我的答案如何让结果节点出现 – JaredPar 2010-08-18 14:16:11

回答

8

一种方式做,这是使用在Visual Studio 2008中添加如果系统的Results视图节点。 Core.dll被加载到进程中,实现IEnumerable<T>的任何类型在扩展名为Results时将获得额外的节点。展开该节点将枚举IEnumerable<T>并显示结果。

F#类型seq只是IEnumerable<T>的别名,因此它具有相同的优点。

results view

默认情况下你不F#看到这一点,因为它没有在System.Core程序使用任何类型的。但是你可以用下面一行强制这个DLL进入进程。

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

出于好奇,当IEnumerable是无限列表时会发生什么? – Gabe 2010-08-18 14:17:56

+2

太棒了。你不需要修改你的代码。它可以工作,如果你在立即窗口中键入:System.Reflection.Assembly.Load(“System.Core,Version = 3.5.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089,processorArchitecture = MSIL”) – 2010-08-18 14:23:49

+0

@Gabe,At那个扩展Result视图的点基本上会挂起,直到对调试器的调用超时(假定IEnumerable是100%托管代码)。如果它是本地的,那么最终可能会出现堆栈溢出,死锁,内存不足......这些是结果视图默认情况下不以内联方式扩展的原因。 – JaredPar 2010-08-18 14:25:57

2

您可以通过将seq放入列表中来强制进行评估。假设qseq<int>,这部作品在监视窗口:

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

BTW:seqIEnumerable的别名。作为升麻types.fsi定义:

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

详细,但它的作品!谢谢。 – 2010-08-18 13:35:40

2

那么,它们显示为关闭的原因是因为这是他们是什么:序列不被评估,直到你真正在代码中使用它们。你可以有一个无限的seq,这将花费相当长的时间才能显示在调试器中。而且,由于评估有一些副作用并不是不可能的,因此对它们进行正确的评估会导致仅在调试器或实际代码中才会显示的问题,而在两者中都不会显示。

如果你知道评估没有问题,你可以把它放在一个列表或另一个非惰性评估的集合中,然后在这里检查它是否正确。

+0

但是任何其他.NET语言中的纯IEnumerable也是懒惰的。这就是为什么当您有C#序列时,Visual Studio会让您手动打开结果视图。我不确定为什么F#需要在这里关闭。 – 2010-08-18 13:37:33

+0

那么,如果我正确读这个问题http://stackoverflow.com/questions/2049806/debugging-an-ienumerable-method,懒惰IEnumerable不应该显示。我的猜测是,调试器足够智能,可以检测IEnumerable何时不被延迟评估(如果它是例如列表),然后在调试器中显示它。 – 2010-08-18 13:52:29

3

测试环境:

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

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

这应该做的工作在快速监视窗口:

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

或者你也可以加入这一行,以确保System.Core程序被加载(和System.Linq的。枚举是可访问的)

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

后,您可以使用此语法在快速监视

System.Linq.Enumerable.ToList(s)