为什么会出现这个编译错误

发布于 2024-12-26 00:05:34 字数 909 浏览 1 评论 0原文

为什么如果我写

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

毁虫ゝ 2025-01-02 00:05:34

if 语句的产生位于 C# 规范的第 8.7.1 节中,内容如下:

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

C# 规范第 8 节的开头明确讨论了嵌入语句< /em> 给出规格后的生产:

嵌入语句:
   堵塞
   空语句
   表达式语句
   选择声明
   迭代语句
   跳转语句
   try语句
   检查语句
   未经检查的语句
   锁定语句
   using 语句 
   收益表

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

void F(bool b) {
     如果 (b)
         整数我 = 44;
} 

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

请注意,赋值算作表达式语句 - 但局部变量声明则不然。 (这是一个声明语句,如第 8.5 节中所示。)

就设计决策而言,声明一个随后无法使用的变量是没有意义的 - 所以它很好< /em> 编译器阻止你这样做。

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.

夜灵血窟げ 2025-01-02 00:05:34

您的第二种形式尝试使用有效的两个语句(变量声明和变量赋值),其中只能使用单个语句。将其视为:

if (!string.IsNullOrEmpty(value))
    string sDirectory;
    sDirectory = Path.GetDirectoryName(value);

您可以看到这不会编译!

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:

if (!string.IsNullOrEmpty(value))
    string sDirectory;
    sDirectory = Path.GetDirectoryName(value);

You can see this won't compile!

墨落成白 2025-01-02 00:05:34

带方括号的第一个版本声明了一个新的局部作用域,您可以在其中声明字符串变量,第二个版本则不然 - 变量声明和赋值被解释为单个嵌入语句,该语句可能不包含变量声明,因此会出现编译错误。

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.

终难遇 2025-01-02 00:05:34
string value = @"C:\";
if (!string.IsNullOrEmpty(value))
string sDirectory = Path.GetDirectoryName(value);

第二条语句被认为是嵌入语句。如果您想在所谓的“代码块”中使用 sDirectory,请用 { } 包围它。在我看来,内联语句(例如您想要做的事情)的可读性较差。

 string value = @"C:\";
 string sDirectory = string.Empty; should be even better way to code..
 if (!string.IsNullOrEmpty(value))
 {
     sDirectory = Path.GetDirectoryName(value);
 } 

或者这

两种情况现在都应该编译

  string value = @"C:\";
  string sDirectory = string.Empty;
  if (!string.IsNullOrEmpty(value))
     sDirectory = Path.GetDirectoryName(value);
string value = @"C:\";
if (!string.IsNullOrEmpty(value))
string sDirectory = Path.GetDirectoryName(value);

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

 string value = @"C:\";
 string sDirectory = string.Empty; should be even better way to code..
 if (!string.IsNullOrEmpty(value))
 {
     sDirectory = Path.GetDirectoryName(value);
 } 

or this

both cases now should compile

  string value = @"C:\";
  string sDirectory = string.Empty;
  if (!string.IsNullOrEmpty(value))
     sDirectory = Path.GetDirectoryName(value);
我不吻晚风 2025-01-02 00:05:34

我不确定 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 whether sDirectory exists or not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文