views:

105

answers:

3

Ok, maybe this isn't so amazing considering I don't really understand how the debugger works in the first place, let alone Edit and Continue, which is totally amazing.

But I was wondering if anyone knew what the debugger is doing with variable declarations in this scenario. I can be debugging through my code, move the line of execution ahead - past a variables initial declaration and assignment, and the code still runs ok. If it's a value type it will have it's default value, for a ref type, null.

So if I create a function that uses a variable before it's declared it won't compile, but if I use the debugger to run it that way it will still run without error. Why is this? And is this related to the fact that you can't put a breakpoint on a declaration?

+3  A: 

Yes, those declarations are more structural. They're part of the locals on the stack that are allocated as the method is called. You can't break on them because they don't really happen where you write them - they're not instructions.

The reason the compiler won't let you use them before they are declared is mostly for your sanity - you always know to look up for a declaration. Complex scoping of variables within a method would further illustrate this point.

uosɐſ
+1  A: 

According to the article Gain performance by not initializing variables:

In .NET, the Common Language Runtime (CLR) expressly initializes all variables as soon as they are created. Value types are initialized to 0 and reference types are initialized to null.

Presumably the debugger already knows about these variables either because the code is already compiled, or (seems less likely now that I am typing it, but) the debugger is smart enough to detect that a variable was declared.

Justin Ethier
that's what I was wondering. It does seem as though the either A)The compiler is just being defensive and trying to protect me from using a variable before I should, or B)The debugger is actually doing something different. and you're right, as soon as I typed that I thought 'damn, I really hope not' ;)
LoveMeSomeCode
+1  A: 

I think that because you are using the debugger, you are confusing the two different activities, compile and execute, and the two different statement types, declarative and functional.

When you compile, a declarative statement tells the compiler to reserve some memory for your variable. It says "oh, you want to declare an integer named "wombatCount"; OK, I'll take address 0x1234 and reserve four bytes just for you and stick a label on them called wombatCount." That happens during the compile, long before you run your code. *

When you execute the code in the debugger, you are running your code, so it already knows about every byte of memory it reserved for you. The variable wombatCount is already associated with four bytes at address 0x1234, so it can immediately access and change that data at any time, not just after your declaration statement. Your program can't, of course, but the debugger can.

The C# language syntax demands that you declare the memory before using it in your code, but that's just part of the language definition, and not a hard-and-fast requirement of all compilers. There are languages that do not require you to pre-declare your variables at all, and there are even some ancient languages where you can declare variables at any point in the code, not just "above" where you'll use them. But language developers now understand that the language syntax is most important for human understanding, and is no longer for ease of machine encoding or helping the compiler writers, so modern language syntaxes are generally created to help the programmers as much as possible. This means making things less confusing, so "declarations must come first" is a common rule to help you avoid mistakes.

(*To be more technically correct, I believe that in .Net the labels are only associated at compile time with a list of pointers that will reserve memory at run time, but the data bytes are not actually allocated until you use them. The difference is internal, and not very important to your understanding. The important takeaway is that a declarative statement declares the label in advance, during compile time.)

John Deters
So at runtime, when is the 4 bytes actually earmarked? When the program first starts up? Or when the variable comes into scope, i.e. at the start of the method in which it is declared?
LoveMeSomeCode
If it is a local variable or a method parameter, it is allocated when the method is called. If the variable is a reference type (not something simple like an int or a bool, and not a struct) then the memory is allocated on the heap when the object is new()'d
uosɐſ