为什么如果我写
无效的主要(){ 字符串值= @C:\\; 如果(!string.IsNullOrEmpty(值)){ 字符串sDirectory = Path.GetDirectoryName(值); }}它编译。
和的情况下,如果我写
无效的主要(){ 字符串值= @C:\\; 如果(!string.IsNullOrEmpty(值)) 字符串sDirectory = Path.GetDirectoryName(值);}这不?
很明显,但从纯功能点在第二的例子是无用的,但为什么它的神奇的成为有用的的第一个的例子,这样的吗?
通过这两个例子中产生的IL code是的究竟的相同。
IL_0000:ldstrC:\\IL_0005:stloc.0IL_0006:ldloc.0IL_0007:拨打System.String.IsNullOrEmptyIL_000C:brtrue.s IL_0015IL_000E:ldloc.0IL_000F:拨打System.IO.Path.GetDirectoryName编辑:
忘了mantion的产生 IL code对于第二种情况(所以这是的不可以编译的情况下),它是没有足够字符串sDirectory =
编译解决方案生产为如果语句在C#规范第8.7.1,和它去像这样的:
if语句: 如果(布尔-EX pression)嵌入语句 如果(布尔-EX pression)嵌入语句别的嵌入语句在C#规范第8节的开始明确地谈到了的嵌入语句的生产给予规范后:
嵌入语句: 块 空语句 前pression语句 选择语句 迭代语句 跳转语句 尝试语句 检查语句 选中语句 锁定声明 使用语句 产量声明
嵌入式语句非终结用于出现在其他语句中的语句。采用嵌入式语句,而不是声明排除了使用声明语句和标记在这些上下文中的语句。这个例子
无效F(布尔B){ 如果(B)的 INT I = 44;}在编译时错误的结果,因为if语句需要一个嵌入语句而不是if分支的声明。如果这个code被允许,那么变量i会被声明,但它可能永远不会被使用。请注意,但是,通过将我的声明在一个块,这个例子是有效的。
请注意,一个任务算作一个的前pression语句的 - 但局部变量声明没有。 (这是一个的声明语句的,如第8.5节)。
在一个设计决策方面,它是没有意义的声明一个变量,你不能再使用 - 所以它的好的编译器阻止你这样做。
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.GetDirectoryNameEDIT:
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:
if-statement: if ( boolean-expression ) embedded-statement if ( boolean-expression ) embedded-statement else embedded-statementThe start of section 8 of the C# spec explicitly talks about the embedded-statement production after giving the specification for it:
embedded-statement: block empty-statement expression-statement selection-statement iteration-statement jump-statement try-statement checked-statement unchecked-statement lock-statement using-statement yield-statementThe embedded-statement nonterminal is used for statements that appear within other statements. The use of embedded-statement rather than statement excludes the use of declaration statements and labeled statements in these contexts. The example
void F(bool b) { if (b) int i = 44; }results in a compile-time error because an if statement requires an embedded-statement rather than a statement for its if branch. If this code were permitted, then the variable i would be declared, but it could never be used. Note, however, that by placing i’s declaration in a block, the example is valid.
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.
更多推荐
为什么这样编译错误
发布评论