6

i got the following code

screenshot

why has x in the finally-block the value 5 instead of beeing "already defined" or having the default value 0?

John Alexiou
  • 28,472
  • 11
  • 77
  • 133
fubo
  • 44,811
  • 17
  • 103
  • 137
  • 3
    That's funny, the debugger indeed shows 1. You can't _use_ `x` in the finally block though, `finally { int x; int y = x; }` won't compile. – C.Evenhuis Mar 31 '14 at 14:17

5 Answers5

7

The lifetime of x is within {...} block, try in your case; however, since there's no zero-initialization of local variables in .Net the next x contains trash which is former x value

try
{
   int x = 5;
}
finally
{
   // x is re-declared; since x is local it contains trash;
   // former x was aquired at the stack, so .Net just moves stack pointer 
   // and doesn't remove former x value
   int x; 
   ...
}

http://msdn.microsoft.com/en-us/library/aa691170(v=vs.71).aspx

...A local variable is not automatically initialized and thus has no default value...

http://msdn.microsoft.com/en-us/library/aa664742(v=vs.71).aspx

...The scope of a local variable declared in a local-variable-declaration is the block in which the declaration occurs...

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Do you have a reference from MSDN stating that local variables are not initialized. I thought the `JIT` uses `default()`, but the compiler enforces initialization to avoid bad code. – John Alexiou Mar 31 '14 at 14:36
  • they have a default value http://stackoverflow.com/questions/2929257/value-of-unassigned-non-nullable-variable-c (see Skeet's answer) – fubo Sep 02 '15 at 12:27
  • @fubo: a *quote* from the answer: "for fields, *not local variables - those can't be read until they've been assigned*... value of `int` is 0..." italic is mine (Dmitry Bychenko). Note, that *local variables* (unlike *fields*) are *not initialized* by zeros – Dmitry Bychenko Sep 02 '15 at 12:33
5

I guess you have set a breakpoint in the finally and looked at x. x has no value according to the C# language spec but the debugger probably looked at the storage location that the first x had and showed you its value.

In real code you would be unable to read from x in the finally.

The debugger does not obey the rules of the language.

usr
  • 168,620
  • 35
  • 240
  • 369
1

You probably use visual studio debugger, that relays on variable names for values watch, and some how shows wrong value, in such messed up cases.

C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72
Tigran
  • 61,654
  • 8
  • 86
  • 123
0

The scope of variable x is limited to try block only, yes Debugger shows the value 5 but if you try to use x variable you will face the problems you mentioned.

Try This:

finally
{
   int x;
   Console.Write(x); //error use of unassigned local variable
}
Sudhakar Tillapudi
  • 25,935
  • 5
  • 37
  • 67
0

why has x in the finally-block the value 1 instead of being "already defined" or having the default value 0?

What you are seeing is the debugger linking up the symbols. It doesn't have a value at all, and in fact if you try and use it you get an unassigned variable error.

Now why doesn't it show as already defined is another question. The answer is that the {} define the declaration space. (In C# variables are defined at the branch level, not the function level). They are in two different declaration spaces and that's why it is allowed. The first x can't spill into where the second x is defined.

What you have is different than

void foo () {
 var x = 2;

 if (true){
   var x = 3;
 }

}

Which isn't allowed.

kemiller2002
  • 113,795
  • 27
  • 197
  • 251