关于在单行条件下省略花括号的规则究竟是什么

时间:2017-03-21 14:57:24

标签: c#

我遇到了一行代码如下:

if (condition)
    // Someone added a comment here
    return "something";

return "something else";

我认为总会返回“某些东西”,但事实并非如此,尽管评论if / condition的工作原理与开发人员的意图相同。

我一直在努力为此找到规则。规则是当存在无支撑条件时执行下一个有效的实际代码行,就好像它是在括号中一样?所以在有效的代码行之前我可以拥有尽可能多的空行和注释吗?

2 个答案:

答案 0 :(得分:1)

C# Language Specification说:

  

从概念上讲,程序是使用三个步骤编译的:

     
      
  1. 转换,将文件从特定字符库和编码方案转换为Unicode字符序列。
  2.   
  3. 词法分析,将Unicode输入字符流转换为标记流。
  4.   
  5. 句法分析,将令牌流转换为可执行代码。
  6.   

...

  

本规范介绍了C#编程语言的语法   使用两个语法。词法语法(§2.2.2)定义了Unicode的方式   字符组合形成行终止符,空格,   注释,令牌和预处理指令。句法语法   (§2.2.3)定义了词法语法产生的标记是如何产生的   结合起来形成C#程序。

我们可以看到令牌被组合起来形成程序,所以在先前的转换之后剩下的令牌是最终被编译的东西。您的问题是关于词法分析,特别是注释,空格和新行如何影响令牌的生成。答案是,除了能够分开令牌之外,它们根本不会影响它们:

  

五个基本元素构成了C#源文件的词法结构:   行终止符(§2.3.1),空格(§2.3.3),注释(§2.3.2),   令牌(§2.4)和预处理指令(§2.5)。其中基本的   元素,只有令牌在C#的句法语法中很重要   程序(§2.2.3)。

     

C#源文件的词法处理包括   将文件缩减为成为输入的标记序列   语法分析。 行终止符,空格和注释   可以用来分隔令牌,预处理指令可以导致   要跳过的源文件的部分,否则这些词汇   元素对C#程序的句法结构没有影响

因此,您的程序可以通过换行符,空白字符或注释来分隔标记,并且它们将编译相同,就好像它们不存在一样。以下是我单独编译的两个示例,并使用ILSpy显示中间语言输出:

        static void Main(string[] args)
        {
            if
(true

                )

                /* comment separating `)` token from the `Console` token */

                Console.WriteLine("something") /* another comment, semicolon token to the right */;
            else                                          // bunch of white space to the left
                Console.
WriteLine("something else")



;

        }

Main()方法的ILSpy输出:

        .method private hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2088
    // Code size 17 (0x11)
    .maxstack 1
    .entrypoint
    .locals init (
        [0] bool
    )

    IL_0000: nop
    IL_0001: ldc.i4.1
    IL_0002: stloc.0
    IL_0003: ldstr "something"
    IL_0008: call void [mscorlib]System.Console::WriteLine(string)
    IL_000d: nop
    IL_000e: br.s IL_0010

    IL_0010: ret
} // end of method Program::Main

更清洁的一个显示相同的ILSpy输出:

static void Main(string[] args)
{        
    if (true) Console.WriteLine("something"); else Console.WriteLine("something else");
}

第二版的ILSpy输出:

    .method private hidebysig static
void Main(
    string[] args
) cil managed
    {
// Method begins at RVA 0x2088
// Code size 17 (0x11)
.maxstack 1
.entrypoint
.locals init (
    [0] bool
)

IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ldstr "something"
IL_0008: call void[mscorlib]
    System.Console::WriteLine(string)
IL_000d: nop
IL_000e: br.s IL_0010


IL_0010: ret
} // end of method Program::Main

答案 1 :(得分:0)

  

我认为总会返回“某事”,但那不是真的

不,如果conditiontrue,则返回"something"。它按预期工作,评论不包括在该代码的评估中。看到这个小提琴:https://dotnetfiddle.net/gHtu5L