2010-08-18 47 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)