views:

71

answers:

3

It's often the case that I can write a nice tight little VB.NET function, and when it comes time to do the Return statement, it's really natural to just return the result of a quick calculation or a method call. However, this makes it difficult if I need to step through the debugger to see what is going to be returned from that Function. For example, take this simple method to illustrate the concept:

Public Shared Function GetAge(ByVal dob As DateTime, ByVal asOfDate As DateTime) As Integer
   If asOfDate.Date < dob.Date Then Return 0
   Dim factor = If(asOfDate.DayOfYear < dob.DayOfYear, 1, 0)
   ' What's going to be returned?
   Return asOfDate.Year - dob.Year - factor ' Imagine that this could be a more complicated calc, or one with side-effects that would prevent me from running it in the immediate window
End Function

I've found myself altering the way I write code just to make debugging easier. So that method would become:

Public Shared Function GetAge(ByVal dob As DateTime, ByVal asOfDate As DateTime) As Integer
   If asOfDate.Date < dob.Date Then Return 0
   Dim factor = If(asOfDate.DayOfYear < dob.DayOfYear, 1, 0)
   Dim result = asOfDate.Year - dob.Year - factor ' I made this variable just for setting a debugging breakpoint
   Return result ' I can now set a breakpoint here, but it seems awkward
End Function

Is there something I'm missing in the debugger that would make it easier to see what a method is going to return rather than always making a result variable or hopping back to the caller to see what came out? It seems awkward to alter the way code is written just to make a simple debugging task easier - it feels like I must be missing something.

+3  A: 

You can set the breakpoint at the End Function line and hover the cursor over the function name.

GSerg
Doesn't seem to work. Tried it in C# too. I'm using VS 2010. Can you provide more details?
mattmc3
The "Local Variables" window includes a variable with the same name as the function. At "End Function" this local variable will be set to the value that is about to be returned.
Tim Murphy
Awesome Tim! That's what I needed. Please post this as an answer instead of a comment so that you can get credit.One additional thing - this solution is VB only (which admittedly was how I asked my question). How do you deal with this in C# where the function name isn't in the locals window?
mattmc3
Maybe they disabled it in VS2010. Alas then. In VS2008 it works as I described. See [the screenshot](http://img682.imageshack.us/img682/7121/debugging.gif).
GSerg
@GSerg - you're right. When I use your code in both VS 2010 and VS 2008, it works. But with my extra Return statement (yes @Enigmativity, go ahead and laugh now), the hover feature doesn't work in 2010. Change your foo() code to this to see (VS 2010 bug):`Public Function foo2(ByVal i As Integer) As Integer`` If i < 0 Then Return -1`` Return i + i``End Function`
mattmc3
Ain't got the VS2010 yet. Works in 2008 anyways. I suggest you go to [connect.microsoft.com](http://connect.microsoft.com) and file it as a bug. Maybe it's even already there.
GSerg
A: 

I'd be inclined to go one step further and remove the Return 0 on the first line of the function so that the only place your code exits the function is at the end.

Public Shared Function GetAge(ByVal dob As DateTime, ByVal asOfDate As DateTime) As Integer
   Dim result = 0
   If asOfDate.Date >= dob.Date Then
      Dim factor = If(asOfDate.DayOfYear < dob.DayOfYear, 1, 0)
      result = asOfDate.Year - dob.Year - factor
   End If
   Return result
End Function

Done this way you only have to worry about one exit point - which makes understanding your code easier, so less debugging - and you get your break-point for free!

Enigmativity
This is really a subjective style thing. Lots of CS classes teach about having 1 exit point - mine included. But in the real world, I've found that it's much easier to put special cases and preconditions at the top of my methods. That way, when you're in the guts of the method, you have certain guarantees about your variables. Regardless, this question isn't at all about this specific code snippet, but the concept of having to have a result variable to do debugging.
mattmc3
@mattmc3 - You make a good point that my answer was a bit tangential to the question. Cheers.
Enigmativity
+1  A: 

Yes, it is awkward. Visual Studio 6 could do this but that got lost in later releases. It isn't that easy to implement, how managed code returns a value is an implementation detail of the JIT compiler. It is kinda obvious for simple return value types like Integer or objects but it gets convoluted when a method returns a structure or decimal.

There isn't really anything wrong with storing it in a variable first, the JIT optimizer will get rid of that variable in most cases. But yes, it looks fugly in the source code.

There is one trick you could use if the return value type is simple, like an integer. Set a breakpoint on the End Function statement, then use Debug + Windows + Registers to display the CPU register values. The EAX register contains the value. Right-click the window and choose Floating point. The ST0 register contains a floating point return type value in 32-bit mode.

Not great, but something to get by when in a pinch.

Hans Passant
Thanks Hans. That EAX registers thing is neat. I've never used that before. The value is in hexidecimal which only makes it feasible for numeric return types, and even then is brutal. But still - that's a great tip.
mattmc3