为什么我写
void Main()
{
string value = @"C:\";
if (!string.IsNullOrEmpty(value)) {
string sDirectory = Path.GetDirectoryName(value);
}
}
Run Code Online (Sandbox Code Playgroud)
它汇编.
如果我写的话
void Main()
{
string value = @"C:\";
if (!string.IsNullOrEmpty(value))
string sDirectory = Path.GetDirectoryName(value);
}
Run Code Online (Sandbox Code Playgroud)
不是吗?
很明显,从纯粹的功能观点来看,第二个例子中变量的声明是无用的,但为什么它在第一个例子中神奇地变得有用,所以呢?
两个示例生成的IL代码完全相同.
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
Run Code Online (Sandbox Code Playgroud)
编辑:
忘了IL为第二种情况生成代码(所以不能编译的情况),这就足够了string sDirectory =
Jon*_*eet 20
if声明的制作在C#规范的第8.7.1节中,它是这样的:
if-statement:
if ( boolean-expression ) embedded-statement
if ( boolean-expression ) embedded-statement else embedded-statement
Run Code Online (Sandbox Code Playgroud)
C#规范第8节的开头在给出规范之后明确地讨论了嵌入式语句的产生:
Run Code Online (Sandbox Code Playgroud)embedded-statement: block empty-statement expression-statement selection-statement iteration-statement jump-statement try-statement checked-statement unchecked-statement lock-statement using-statement yield-statement嵌入语句非终结符用于出现在其他语句中的语句.嵌入式语句而不是语句的使用排除了在这些上下文中使用声明语句和带标签的语句.这个例子
Run Code Online (Sandbox Code Playgroud)void F(bool b) { if (b) int i = 44; }导致编译时错误,因为if语句需要嵌入语句而不是if语句的语句.如果允许此代码,那么将声明变量i,但它永远不会被使用.但请注意,通过将i的声明放在块中,该示例是有效的.
请注意,赋值计为表达式语句 - 但局部变量声明不计算.(这是一份声明声明,如第8.5节所述.)
就设计决策而言,声明一个你不能使用的变量是没有意义的 - 所以编译器阻止你做这件事是好的.
你的第二种形式试图使用有效的两个语句(一个变量声明和一个变量赋值),其中只能使用一个语句.把它想象成:
if (!string.IsNullOrEmpty(value))
string sDirectory;
sDirectory = Path.GetDirectoryName(value);
Run Code Online (Sandbox Code Playgroud)
你可以看到这不会编译!