为什么这个编译错误 [英] Why this compile error

查看:24
本文介绍了为什么这个编译错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么如果我写

void Main(){字符串值 = @"C:";if (!string.IsNullOrEmpty(value)) {字符串 sDirectory = Path.GetDirectoryName(value);}}

它编译.<​​/p>

如果我写了

void Main(){字符串值 = @"C:";if (!string.IsNullOrEmpty(value))字符串 sDirectory = Path.GetDirectoryName(value);}

不是吗?

很明显,从纯函数的角度来看,第二个示例中的变量声明是无用的,但是为什么它神奇地第一 示例,所以?

两个示例生成的 IL 代码完全相同.

IL_0000: ldstr "C:"IL_0005:stloc.0IL_0006: ldloc.0IL_0007:调用 System.String.IsNullOrEmptyIL_000C:brtrue.s IL_0015IL_000E: ldloc.0IL_000F:调用 System.IO.Path.GetDirectoryName

忘记说明为第二种情况生成 IL 代码(因此不可编译的情况),在没有 string sDirectory 的情况下编译就足够了=

解决方案

if 语句的产生式在 C# 规范的第 8.7.1 节中,它是这样的:

if 语句:if ( boolean-expression ) 嵌入语句if ( boolean-expression ) 嵌入语句 else 嵌入语句

C# 规范第 8 节的开头明确谈到了embedded-statement 产生式,然后给出了它的规范:

<块引用>

嵌入语句:堵塞空语句表达式语句选择声明迭代语句跳转语句尝试语句检查语句未经检查的语句锁定语句使用语句产量声明

嵌入式语句非终结符用于出现在其他语句中的语句.使用嵌入语句而不是语句排除了在这些上下文中使用声明语句和标记语句.例子

void F(bool b) {如果 (b)国际我= 44;}

导致编译时错误,因为 if 语句需要嵌入语句而不是 if 分支的语句.如果允许使用此代码,则将声明变量 i,但永远无法使用它.但是请注意,通过将 i 的声明放在块中,该示例是有效的.

请注意,赋值算作表达式语句 - 但局部变量声明不算.(这是一个声明语句,如第 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.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:

if-statement:
    if   ( boolean-expression )   embedded-statement
    if   ( boolean-expression )   embedded-statement   else   embedded-statement

The 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-statement

The 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.

这篇关于为什么这个编译错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆