Friday, August 20, 2010

The evil debugger



Let's take a look at the following piece of C# code:





1:  using System; 
2:  using System.Collections.Generic; 
3:  using System.Linq; 
4:  using System.Text; 

5:  namespace ConsoleApplication1 { 
6:    class Program { 
7:      private string myString = null; 
8:      public string MyString { 
9:        get { 
10:          if (myString == null) { 
11:            myString = "Bad string"; 
12:          } 
13:          return myString; 
14:        } 
15:        set { 
16:          if (myString == null) { 
17:            myString = value; 
18:          } 
19:        } 
20:      } 
21:      public override string ToString() { 
22:        return MyString; 
23:      } 
24:      static void Main(string[] args) { 
25:        Program program = new Program(); 
26:        program.MyString = "Good string"; 
27:        Console.WriteLine(program); 
28:      } 
29:    } 
30:  }  


The result, as you would expect should be "Good string" written to the console. That is, when you run it from the command line.
Suppose I run it in Visual Studio .NET 2008 and I put a breakpoint at line 27 in the debugger. Then I debug the program, I reach line 27, I move to line 28 and the result is of course "Good string".
Let's put a breakpoint at line 26. You'd say "what does the breakpoint have to do with the result ?" Well, it does, because in this case, "Bad string" will be displayed. This is like Heisenberg principle (or the observer effect), isn't it ? When we debug, we actually influence the result. This is possible because when the breakpoint is set at line 26, MyString getter is executed and in effect myString is set to "Bad string". After that trying to set myString to "Good string" can't succeed because in the setter the test (myString == null) is false. At line 27 ToString() is called, displaying of course "Bad string".

The default behavior of the debugger in Visual Studio .NET 2008 is to evaluate the properties when the debugger hits them. Also, the ToString() method is called by default whenever you hover with the mouse pointer over an instance (like "program" in line 26).
You can disable these behaviors under Tools -> Options -> Debugging -> General.

It's good to know this, because as you can see, .NET properties and ToString() evaluation in VS.NET can give you lots of headaches.


No comments:

Post a Comment