I think this issue is related more to the generated IL, than the readable
of the source code.
Compile the following code, and then inspect the generated IL:
C#:
static void Main()
{
string f = "first text";
{
string i = "inner text";
Console.WriteLine(f);
Console.WriteLine(i);
}
string s = "second text";
Console.WriteLine(f);
Console.WriteLine(s);
}
IL:
..method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 1
.locals init ( <--- here's the declaration for all the local
variables
[0] string f,
[1] string i,
[2] string s)
L_0000: nop
L_0001: ldstr "first text"
L_0006: stloc.0 <--- store the text in the line before, in
the local variable at index 0 ( f )
L_0007: nop
L_0008: ldstr "inner text"
L_000d: stloc.1 <--- store the text in the line before, in the
local variable at index 1 ( i )
L_000e: ldloc.0
L_000f: call void [mscorlib]System.Console::WriteLine(string)
L_0014: nop
L_0015: ldloc.1
L_0016: call void [mscorlib]System.Console::WriteLine(string)
L_001b: nop
L_001c: nop
L_001d: ldstr "second text"
L_0022: stloc.2 <--- store the text in the line before, in the
local variable at index 2 ( s )
L_0023: ldloc.0
L_0024: call void [mscorlib]System.Console::WriteLine(string)
L_0029: nop
L_002a: ldloc.2
L_002b: call void [mscorlib]System.Console::WriteLine(string)
L_0030: nop
L_0031: ret
}
As you see, IL doesn't know about scoped local variables. There's a
declaration block at the start of the method, where all the local variables
are stated. From this point of view, is natural then that the C# compiler
doesn´t admit the following:
{
string s = "x";
}
string s = "y";
But now, what happens when two variables are declared with the same name,
but into different scopes inside the same method??
C#: (watch the local variable i)
static void Main()
{
string f = "first text";
{
string i = "inner text";
Console.WriteLine(f);
Console.WriteLine(i);
}
string s = "second text";
Console.WriteLine(f);
Console.WriteLine(s);
{
string i = "other inner text";
Console.WriteLine(f);
Console.WriteLine(i);
}
}
IL:
..method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] string f,
[1] string i, <-- Just declared once!
[2] string s)
L_0000: nop
L_0001: ldstr "first text"
L_0006: stloc.0
L_0007: nop
L_0008: ldstr "inner text"
L_000d: stloc.1 <--- First use of local variable i
L_000e: ldloc.0
L_000f: call void [mscorlib]System.Console::WriteLine(string)
L_0014: nop
L_0015: ldloc.1
L_0016: call void [mscorlib]System.Console::WriteLine(string)
L_001b: nop
L_001c: nop
L_001d: ldstr "second text"
L_0022: stloc.2
L_0023: ldloc.0
L_0024: call void [mscorlib]System.Console::WriteLine(string)
L_0029: nop
L_002a: ldloc.2
L_002b: call void [mscorlib]System.Console::WriteLine(string)
L_0030: nop
L_0031: nop
L_0032: ldstr "other inner text"
L_0037: stloc.1 <-- The compiler re-use the memory allocation!!!
L_0038: ldloc.0
L_0039: call void [mscorlib]System.Console::WriteLine(string)
L_003e: nop
L_003f: ldloc.1
L_0040: call void [mscorlib]System.Console::WriteLine(string)
L_0045: nop
L_0046: nop
L_0047: ret
}
As the local variable i is declared in separated scopes inside the same
method, the compiler "thinks" is safe to re-use the same memory allocation
for both...
This is a little bit clearer to me....
Greetings,
Pedro Luna
pagerintas pritupimas said:
Code sample 1:
if (true)
{
string message = string.Format("Message {0}.", 1);
Console.WriteLine(message);
}
string message = string.Format("Message {0}.", 2);
Console.WriteLine(message);
Compiler says: "You can't do that. It would be so hard to read this piece
of code."
Code sample 2:
if (true)
{
string message = string.Format("Message {0}.", 1);
Console.WriteLine(message);
}
{
string message = string.Format("Message {0}.", 2);
Console.WriteLine(message);
}
Compiler says: "It's so much better now, the code is much more readable,
go ahead."
If code readability is the only argument in this situation, then I find it
hardly convincing. Anyway, thanks everybody for taking time to answer :]