Friday, March 7, 2008

DebuggerStepThroughAttribute

Here's a good one I was reminded of the other day. I was writing some code of the form we've all seen a thousand times before:

 

public Foo Bar {
  get { return _bar; }
  set { _bar = value; }
}

 

Even with automatic properties in the latest version of C#, you still wind up writing code like this a lot. Unless you're fortunate enough to be writing code in a more advanced language…like Lisp. :) (Sorry, had to.)

 

Normally this is no big deal, but there is one time where this construct can get really annoying: when you're debugging and the property is frequently accessed as the means to get somewhere else. In my code that will often look like this:

 

public SomethingProvider SomethingProvider {
  get { return _somethingProvider; }
}

 

when I have some service that I've abstracted, maybe to make testing easier. As a result, my code has lots of calls in it like this:

 

SomethingProvider.PerformOperation(arg1, arg2, …);

 

When I hit that line, I want to debug into it, but of course when I hit "step into" I wind up on the property accessor. It's even worse when there are multiple properties involved, as for example in code like this:

 

SomethingProvider.PerformOperation(OtherProvider.RetrieveValue(), YetAnotherProvider.Calculate());

 

By the time I've finished stepping in and out of that, I'm all, "Aargh! Just take me to the code!" Luckily, there's an attribute that lets you skip all these piddly statements: DebuggerStepThroughAttribute. You use it like any other attribute - apply it to a method, a whole class, or a property accessor. Note that you can't apply it to a property as a whole - it has to go on the individual getters or settors, like so:

 

public SomethingProvider SomethingProvider {
  [DebuggerStepThrough]
  get { return _somethingProvider; }
}

 

Put enough of these in and stepping in to a compound expression becomes much less tedious. Yay!

 

I don't think I'd recommend generally putting this attribute on anything but simple one-line properties of the form I've shown here, and even then you want to be careful: debugging is complicated, and I know I can screw up even simple property access - sometimes stepping into those things is actually useful, as it shows you that you cut and pasted one too many times and wound up returning the wrong value.

 

That said, you can still set breakpoints on code you've applied the attribute to, and the breakpoints will still fire.

6 comments:

  1. I'm using Resharper, so what I usually do, is Ctrl-B to get to the function that I'm interested in, and then Ctrl-F10, to run the code upto the line the cursor is on.

    ReplyDelete
  2. I don't think you need resharper for that. F12 will go to a function definition, and "run to cursor" is a command you can easily bind to a key sequence in VS. It's a good idea, though.



    I didn't much care for Resharper when I used it - it was too invasive and painfully slow. Plus, I understand they don't support VS2008 yet, which is my primary dev environment. But lots of people seem to like it!

    ReplyDelete
  3. Yes, "Run To" is a standard debugger function. I don't think ReSharper adds any debugger functionality at all, it's just as interface enhancer. (And indeed painfully slow.)



    Anyway, thanks for this tip! During debugging it's easy to hit several trivial getters on a single code line before anything interesting happens, and it's driving me insane. I think I'll be using this attribute a lot.

    ReplyDelete
  4. anyone know how the DebuggerStepThroughAttribute is different than the DebuggerStepperBoundaryAttribute or the DebuggerHiddenAttribute.



    they all seem to suggest that you could "step over" code in the affected method.



    ReplyDelete
  5. The remarks in the docs seem fairly clear - are you observing a different behavior from what's outlined there?

    ReplyDelete
  6. You can right click the line and Step Into Specific to choose exactly what you want to step into. When you're working on a team, liberal use of these kinds of attributes can get pretty annoying.

    ReplyDelete