{"id":6873,"date":"2005-12-02T13:58:00","date_gmt":"2005-12-02T13:58:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2005\/12\/02\/ide-debugger-enhancements-type-viewer-attributes-and-type-visualizers-by-luca-dellamore\/"},"modified":"2024-07-05T14:53:03","modified_gmt":"2024-07-05T21:53:03","slug":"ide-debugger-enhancements-type-viewer-attributes-and-type-visualizers-by-luca-dellamore","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/ide-debugger-enhancements-type-viewer-attributes-and-type-visualizers-by-luca-dellamore\/","title":{"rendered":"IDE Debugger enhancements (type viewer attributes and type visualizers) by Luca Dellamore"},"content":{"rendered":"<p class=\"MsoNormal\">In Visual Studio 2003 it was sometimes difficult to examine large complicated objects in the debugger (since it is simply impossible for any debugger to analyze arbitrary objects and figure out what the developer is really interested in knowing).<\/p>\n<p class=\"MsoNormal\">To improve this scenario in Visual studio 2005 we introduced the concept of attributed debugging, that allows the developer of the type to also specify what that type will look like when it&rsquo;s being debugged.<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><b><span>DebuggerDisplay Attribute<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\">The DebuggerDisplay attribute let us choose how we want to display a type in the debugger: take for example the 2 following variables.<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><span><span><font color=\"#000080\">&nbsp;&nbsp;&nbsp;&nbsp;Dim overflow As New OverflowException<br \/>&nbsp;&nbsp;&nbsp; Dim myPoint As New System.Drawing.Point(x:=3, y:=4)<\/font><br \/><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\">In Visual Studio 2003 when you added them to the watch window this was what you would see:<span><\/p>\n<p><\/span><\/p>\n<p><img decoding=\"async\" src=\"\"> <\/p>\n<p class=\"MsoNormal\">Check out instead the new Visual Studio 2005 view: much more information without having to drill down the TreeView.<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\"> <\/p>\n<p class=\"MsoNormal\">This is a simple example to show you the syntax:<\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font color=\"#000080\">&lt;DebuggerDisplay(&#8220;Employee: {FullName}&#8221;)&gt; Public Class Employee<br \/>&nbsp;&nbsp;&nbsp; Public FirstName As String<br \/>&nbsp;&nbsp;&nbsp; Public LastName As String<br \/>&nbsp;&nbsp;&nbsp; Public Salary As Decimal<br \/>&nbsp;&nbsp;&nbsp; Public JobTitle As String<br \/>&nbsp;&nbsp;&nbsp; Public ReadOnly Property FullName() As String<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return FirstName &amp; &#8221; &#8221; &amp; LastName<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Get<br \/>&nbsp;&nbsp;&nbsp; End Property<br \/>End Class<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><span><\/p>\n<p><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\">Notice that FullName is inside curly brackets: this means that Visual Studio will evaluate the expression and in this case it will display the return value of the Property FullName.<span><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\">So if you run the following code:<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><span><font color=\"#000080\">&#8216;DebuggerDisplay attribute<br \/>Dim emp As New Employee<br \/>emp.FirstName = &#8220;Thomas&#8221;<br \/>emp.LastName = &#8220;Andersen&#8221;<br \/>emp.Salary = 65000<br \/>emp.JobTitle = &#8220;Software Development Engineer&#8221;<\/font><\/span><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\">and in debug mode you hover over your variable &lsquo;emp&rsquo; you will see the following tip (that gives you more information at a glance that simply the class name)<\/p>\n<p><img decoding=\"async\" src=\"\"> <\/p>\n<p><b><span>DebuggerTypeProxy Attribute<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<p>If we want to have even more control of display of a type at debug time we can use the DebuggerTypeProxy attribute that let us specify a display proxy for the type:<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><span><font color=\"#000080\">&lt;DebuggerTypeProxy(GetType(Employee.View))&gt; &lt;DebuggerDisplay(&#8220;Employee: {FullName}&#8221;)&gt; _<br \/>Public Class Employee<br \/>&nbsp;&nbsp;&nbsp; Public FirstName As String<br \/>&nbsp;&nbsp;&nbsp; Public LastName As String<br \/>&nbsp;&nbsp;&nbsp; Public Salary As Decimal<br \/>&nbsp;&nbsp;&nbsp; Public JobTitle As String<br \/>&nbsp;&nbsp;&nbsp; Public ReadOnly Property FullName() As String<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return FirstName &amp; &#8221; &#8221; &amp; LastName<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Get<br \/>&nbsp;&nbsp;&nbsp; End Property<br \/>&nbsp;&nbsp;&nbsp; &#8216;this is the Proxy class that will be shown at runtime<br \/>&nbsp;&nbsp;&nbsp; Friend Class View<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Private privateInstance As Employee = Nothing<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Public Sub New(ByVal a As Employee)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Me.privateInstance = a<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Sub<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Public ReadOnly Property JobTitle() As String<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return privateInstance.JobTitle<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Get<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Property<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Public ReadOnly Property FullName() As String<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return privateInstance.FullName<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Get<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Property<br \/>&nbsp;&nbsp;&nbsp; End Class &#8216;View<br \/>End Class<br \/><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p><span>Now the Employee class will display like so: <\/span><\/p>\n<p><img decoding=\"async\" src=\"\"> <\/p>\n<p class=\"MsoNormal\">Note that only public members of the Proxy class are shown (unless you change the option: Tools<span><span>&agrave;<\/span><\/span>Options<span><span>&agrave;<\/span><\/span> Debugging<span><span>&agrave;<\/span><\/span> General<span><span>&agrave;<\/span><\/span> Show all members for non-user objects in variable window (Visual Basic only))<\/p>\n<p class=\"MsoNormal\">Note that if you are debugging in your project you will see also private members: the picture above was taken when using a dll reference.<\/p>\n<p class=\"MsoNormal\">This attribute is used for example in some Framework classes like the Hashtable.<\/p>\n<p class=\"MsoNormal\">If you want to see the real structure of a type and not the proxy class you can go to <\/p>\n<p class=\"MsoNormal\">Tools<span><span>&agrave;<\/span><\/span> Options<span><span>&agrave;<\/span><\/span> Debugging<span><span>&agrave;<\/span><\/span> General and check the box: Show raw structure of objects in variables window<\/p>\n<p class=\"MsoNormal\"><b><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\"><b><span>Type Visualizers<\/p>\n<p><\/span><\/b><\/p>\n<p class=\"MsoNormal\">My favorite new enhancement is the introduction of type visualizers: some types (for example the Dataset) simply are not easily viewable in the watch window: that is why we have now in Visual Studio the option to create an entirely new view of the data.<\/p>\n<p class=\"MsoNormal\">Run the following code that will create a simple dataset, add &lsquo;ds&rsquo; to the watch window and click the magnifying glass to view the DataSet visualizer (btw: you can also edit the data of your DataSet in the Visualizer)<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><span><span><font color=\"#000080\">&nbsp;&nbsp; Dim ds As New DataSet<br \/>&nbsp;&nbsp; ds.Tables.Add(New DataTable(&#8220;Friends&#8221;))<br \/>&nbsp;&nbsp; ds.Tables(0).Columns.Add(&#8220;Name&#8221;, GetType(String))<br \/>&nbsp;&nbsp; ds.Tables(0).Columns.Add(&#8220;Age&#8221;, GetType(Integer))<br \/>&nbsp;&nbsp; ds.Tables(0).Rows.Add(New Object() {&#8220;Marc&#8221;, 14})<br \/>&nbsp;&nbsp; ds.Tables(0).Rows.Add(New Object() {&#8220;Luca&#8221;, 12})<br \/>&nbsp;&nbsp; ds.Tables(0).Rows.Add(New Object() {&#8220;Jessica&#8221;, 9})<br \/>&nbsp;&nbsp; Dim xmlString As String = ds.GetXml<\/font><\/span><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><\/span><\/p>\n<p><img decoding=\"async\" src=\"\"> <\/p>\n<p><img decoding=\"async\" src=\"\"> <\/p>\n<p class=\"MsoNormal\">If you add the &lsquo;xmlString&rsquo; variable form the previous code snippet to the watch window you can try also the 3 default visualizers for the String type: the following is a picture of the XML Visualizer (no more cut and paste of long strings into notepad).<\/p>\n<p><img decoding=\"async\" src=\"\"> <\/p>\n<p class=\"MsoNormal\">If you want to see how to create a very simple Visualizer you can find a VB example in Deep&rsquo;s blog (Deep is a friend that works in the C# group but he included also a sample in VB in his post: thanks Deep for thinking about us too)<\/p>\n<p class=\"MsoNormal\"><a href=\"http:\/\/blogs.msdn.com\/deeptanshuv\/archive\/2005\/03\/21\/400194.aspx\">http:\/\/blogs.msdn.com\/deeptanshuv\/archive\/2005\/03\/21\/400194.aspx<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Happy debugging!<\/p>\n<p class=\"MsoNormal\">Luca Dellamore<\/p>\n<p class=\"MsoNormal\">Visual Basic Test Team<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Visual Studio 2003 it was sometimes difficult to examine large complicated objects in the debugger (since it is simply impossible for any debugger to analyze arbitrary objects and figure out what the developer is really interested in knowing). To improve this scenario in Visual studio 2005 we introduced the concept of attributed debugging, that [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[192,195],"tags":[74,165],"class_list":["post-6873","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-visual-basic","tag-ide","tag-vb2005"],"acf":[],"blog_post_summary":"<p>In Visual Studio 2003 it was sometimes difficult to examine large complicated objects in the debugger (since it is simply impossible for any debugger to analyze arbitrary objects and figure out what the developer is really interested in knowing). To improve this scenario in Visual studio 2005 we introduced the concept of attributed debugging, that [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/6873","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=6873"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/6873\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=6873"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=6873"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=6873"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}