views:

541

answers:

3

I've seen several classes in the framework with this behavior (a refresh symbol in the watch window, and a warning). Is this controlled by an Attribute? If so, how can I emulate this in my library?

EDIT: Thanks for the info! To clarify, I am developing a framework with properties that must access data from a single thread. Unfortunately, I am getting some odd behavior when I am in the debugger because of watch windows, etc. I have experience with the Debugger Browsable attribute; however, I would prefer to display the properties after the main thread has accessed / set them. I have seen, especially in IEnumerables that the debugger will not evaluate without user input. ...Is there any way to flag these properties as requiring "Implicit Evaluation", Or can I not have my cake and eat it too?

+4  A: 

This is not controlled by attributes. It's an inherent feature of the debugger.

The underlying reason for this feature is to prevent unwanted function evaluations by the user. Func Evals are a dangerous operation in the debugger and can cause significant slow downs or corrupt program state. The debugger takes great care to make sure that it doesn't inadvertently do extra func evals that may degrade your debugging experience.

In the case where there is an item in the watch/locals/auto window that may cause a func eval and the debugger does not believe a func eval should happen, the value will grey out and a refresh button will appear in the value column. Clicking on that button is telling the debugger, "no really I want to evaluate that expression".

There are many reasons why this will happen in the debugger. The following 2 though are the most likely.

Implicit Property Evaluation Is Disabled

Tools -> Debugger -> Options -> Enable Implicit Property Evaluation

If this value is unchecked, you are telling the debugger please don't auto-evaluate properties. Properties under the hood are just function calls. They are generally safer than normal function calls but not always.

But you can still force properties to evaluate by typing them directly into the watch window. If you type 2 in a row, the first value will become "stale". This is because typing a second expression in the watch window will cause all other expressions to get re-evaluated. Why? Because the act of evaluating any expression could have altered the results of the others.

Because implicit func eval is turned off the first property will not auto-evaluate and you must force it.

Func Eval and Step

If you add an expression to the watch window which does a function evaluation and then do a step operation, the value will be "staled" in the watch window.

This is done for many reasons, one of the most impactful reasons though is stepping performance. It's very common for a user to type many expressions in the watch window, and it's definitely not rare to have a function evaluation. One at a time these aren't very slow. But imagine you're trying to step quickly through some code and you had 10 func evals in the watch window. That can quickly add up and significantly degrade your stepping experience. So func evals are not automatically re-evaluated.

JaredPar
I ruined some debugging sessions by moving my mouse where I shouldn't and evaluating properties of mocks. That threw the expectactions I had set up through the window.
Martinho Fernandes
+4  A: 

While this doesn't generate the refresh icon you are referring to, a very useful attribute is System.Diagnostics.DebuggerBrowsableAttribute, which allows you to hide fields from ever showing up in Watch windows. This is useful when fields and duplicated by property accessors and they don't need to show up twice, or if a property performs some substantial operation (like what you're suggesting) and you need to suppress it always so that the debugger doesn't evaluate it.

Andrew Arnott
+1  A: 

This isn't exactly what you are looking for, but if you apply the [DebuggerStepThrough] attribute to the getter/setter of the property it will prevent the debugger from breaking on the property unless explicitly setting a breakpoint on the line. This could be useful if you want to wait and set the breakpoint after you know it's safe to evaluate. You could also use [DebuggerHidden] if you want to hide it from debugging all together.

Quintin Robinson