为什么会出现这个编译错误
为什么如果我写
void Main()
{
string value = @"C:\";
if (!string.IsNullOrEmpty(value)) {
string sDirectory = Path.GetDirectoryName(value);
}
}
它可以编译。
万一我写
void Main()
{
string value = @"C:\";
if (!string.IsNullOrEmpty(value))
string sDirectory = Path.GetDirectoryName(value);
}
它不呢?
很明显,从纯功能的角度来看,第二个示例中的变量声明是无用的,但为什么它在第一个示例中神奇地变得有用例如,所以?
这两个示例生成的 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
编辑:
忘记指出要为第二种情况生成IL
代码(因此不可编译的情况),编译就足够了没有 string sDirectory =
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 =
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
if
语句的产生位于 C# 规范的第 8.7.1 节中,内容如下:C# 规范第 8 节的开头明确讨论了嵌入语句< /em> 给出规格后的生产:
请注意,赋值算作表达式语句 - 但局部变量声明则不然。 (这是一个声明语句,如第 8.5 节中所示。)
就设计决策而言,声明一个随后无法使用的变量是没有意义的 - 所以它很好< /em> 编译器阻止你这样做。
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.
您的第二种形式尝试使用有效的两个语句(变量声明和变量赋值),其中只能使用单个语句。将其视为:
您可以看到这不会编译!
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 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.
第二条语句被认为是嵌入语句。如果您想在所谓的“代码块”中使用 sDirectory,请用 { } 包围它。在我看来,内联语句(例如您想要做的事情)的可读性较差。
或者这
两种情况现在都应该编译
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
我不确定 C# 的情况,但其他语言的情况就是这样:因为 { } 打开一个块,因此打开一个新的作用域。如果省略它们,则该变量将在
Main
范围内声明,因此只会在某些时候声明,因此编译器随后不知道sDirectory 存在或不存在。
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.