Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the Visual Studio debugger decide which values can be viewed with the Text/XML/HTML Visualizer?

I noticed that when I view variables of certain types, such as XElement, in the Watch window in Visual Studio, if I click on the Debug Visualizers magnifying glass, the same visualizers that apply on strings (Text, XML, HTML) appear. I haven't seen this happen on any other type before. How does the debugger decide to do this?

EDIT: Here's a screenshot from the Watch window, demonstrating that XElement gets to be displayed with Text Visualizer, while System.Version (which also implements ToString) does not. enter image description here

like image 462
Omer Raviv Avatar asked Feb 27 '14 19:02

Omer Raviv


1 Answers

This is actually a bit of a complex question because there are multiple pieces of the expression evaluator that control the display of custom viewers.

For the Text, XML and HTML viewer the answer is pretty easy because they are visualizers built into the debugger. If IDebugProperty2::GetPropertyInfo returns DBG_ATTRIB_VALUE_RAW_STRING as a part of the attribute flags then this visualizer will be displayed. When the user selects on of these viewers the debugger will call back into IDebugProperty3::GetStringChars / GetStrigCharLength in order to get the string value to pass to the visualizer.

For user defined visualizers though it is quite a bit more involved probably a bit to much for an answer here. MSDN does have a bit of information on how to do this though

http://msdn.microsoft.com/en-us/library/vstudio/bb162331(v=vs.100).aspx http://msdn.microsoft.com/en-us/library/vstudio/bb146621(v=vs.100).aspx

Now lets consider the specific example called out in this question: Version vs. XElement. The first thing to note is that you get different behavior depending on which language you are debugging in. C#, as you noticed, shows the visualizer only for XElement while VB.Net will show the visualizer for both XElement and Version. This is unsurprising in some ways because the visualizer flag is controlled by the EE and each language has their own implementation

C# algorithm

If the value is typed to String or has an implicit reference conversion to XNode then the visualizer is displayed.

In this case XElement derives from XNode hence it gets the visualizer. The Version type does not derive from XNode and it's not String so it does not get the visualizer

VB.Net algorithm

If the value being displayed meets one of the following then the visualizer is displayed

  1. String or has a ToString override
  2. Has a DebuggerDisplay which points to a value that qualifies for 1 or 2

In this case both XElement and Version override ToString hence the visualizer is shown in both cases

Why the difference?

Beats me. When I wrote the VB.Net implementation I wanted to support the visualizer in as many places as possible (it's really useful). Hence whenever the final value being displayed was a String I displayed the visualizer. I didn't really think to consult the C# team when I made this decision. Until I researched the code base to answer this question I wasn't even aware there was a difference :)

like image 56
JaredPar Avatar answered Oct 05 '22 23:10

JaredPar