Why if I write
void Main()
{
string value = @"C:\";
if (!string.IsNullOrEmpty(value)) {
string sDirectory = Path.GetDirectoryName(value);
}
}
it compiles.
And in case if I write
void Main()
{
string value = @"C:\";
if (!string.IsNullOrEmpty(value))
string sDirectory = Path.GetDirectoryName(value);
}
It doesn't ?
It's clear that from pure functional point of view the declaration of the variable in the second example is useless, but why it magically becomes usefull in first example, so ?
The IL code produced by both examples is exactly the same.
IL_0000: ldstr "C:\"
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: call System.String.IsNullOrEmpty
IL_000C: brtrue.s IL_0015
IL_000E: ldloc.0
IL_000F: call System.IO.Path.GetDirectoryName
EDIT:
Forgot to mantion that to produce the IL
code for the second case (so the case which is not compilable), it's enough to compile without string sDirectory =
The production for an
if
statement is in section 8.7.1 of the C# spec, and it goes like this:The start of section 8 of the C# spec explicitly talks about the embedded-statement production after giving the specification for it:
Note that an assignment counts as an expression-statement - but a local variable declaration doesn't. (That's a declaration-statement, as in section 8.5.)
In terms of a design decision, it makes no sense to declare a variable that you can't then use - so it's good that the compiler stops you from doing it.
I am not sure for C#, but this is the case for other languages: because { } open a block and therefore a new scope. If you omit them, then the variable is being declared in the scope of
Main
and so will only be declared some of the time, and so the compiler doesn't know afterwards whethersDirectory
exists or not.The first version with the brackets declares a new local scope within which you declare a string variable, the second version doesn't - the variable declaration and assignment is interpreted as a single embedded statement which may not include variable declarations, hence the compilation error.
Your second form tries to use what is effectively two statements (a variable declaration and a variable assignment) where only a single statement could be used. Think of it as:
You can see this won't compile!
The second statement is what is considered an embedded statement.. if you want to use sDirectory within what is called a "Code Block" wrap { } around it. inline statements like what you are trying to do in my opinion make for poor readability..
or this
both cases now should compile