5

我遇到了一些有趣的东西,我似乎找不到更多信息或正确的名称。

我想我们大多数人都知道,如果你有多个using块,你只需要在最后一个后面加上括号using

using (FileStream fileStream = new FileStream(zipFilePath, FileMode.Open))
using (ZipInputStream zipStream = new ZipInputStream(fileStream))
{
    //stuff
}

然而,我发现下面的代码也可以工作,没有括号紧跟在后面using,捎带while

using (BinaryWriter br = new BinaryWriter(context.Response.OutputStream))
while (true)
{
    //stuff
}

有谁知道这种允许代码块合并的语言“功能”的名称?

4

7 回答 7

7

是的,这是有意的。这是 C♯ 继承自 C 和 C++ 的习语。如果你有一个用大括号括起来的语句,大括号通常是可选的。是否使用它们主要是样式和可读性的问题。对于嵌套using语句,通常省略外层的大括号。

语言语法

在语法上,一个using块后面跟着一个语句。通常这是一个块语句,但它不是必须的。

有多种说法。有表达式语句,如a = b;. 有迭代语句,如while (boolean-expression) { ... }. 这里整个while循环算作一条语句。还有块语句,它由一个或多个用花括号括起来的语句组成。

有关语句的正式规范,请参阅 C# 语言规范、附录 C. 语法、§C.2.5语句

语句:
    标记语句
    声明语句
    嵌入语句
嵌入语句
    
    空语句
    表达式语句
    选择语句
    迭代语句
    跳转语句
    尝试语句
    检查语句
    未检查语句
    锁定语句
    使用语句

    
{ 语句语句列表选择 }

如果您只有一条语句,通常可以省略语句周围的花括号。这些是等价的:

if (condition) statement;
if (condition) { statement; }

就像这些:

using (...)
using (...)
    statement;

using (...)
using (...)
{
    statement;
}

using (...)
{
    using (...)
    {
        statement;
    }
}

有时需要

也有需要大括号的例外情况。方法体必须总是有花括号。它融入了语法。

方法体:
    块
    
;

同样,//try子句必须花括号。和 也是一样的。您可以在语法中看到这一点。catch 子句被定义为“catch”而不是“catch语句”。catchfinallycheckedunchecked

try-statement:
    
try block catch-clauses
    
try block finally-clause
    
try block catch-clauses finally-clause
specific-catch-clause:
    
类类型标识符opt block general-catch-clause: block finally-clause: block checked-statement: block unchecked-声明:catch ( )

    
catch

    
finally

    
checked

    
unchecked

为什么是这样?简短的回答是它消除了语法中的歧义。有关深入的解释,请参阅Eric Lippert 对这种不一致的解释。

于 2012-12-18T19:05:31.837 回答
3

{ }创建单个代码块。如果你没有它们,那么下一条语句就是被执行的块。因此,您所做的事情是有道理的,因为这using将适用于while.

于 2012-12-18T18:59:56.393 回答
2

正如 Eric Lippert 所描述的,每当您有一个if/ else/ for/ while/ using/ foreach/ do/ case/switch等表达式时,它总是后跟一条语句。使用大括号 ( { }) 只是使大括号内的所有内容成为一个语句的一种方式。任何时候你自然只有一个语句,很少需要(除了可能的可读性)使用大括号。现在,在大多数情况下,可读性已经足够了,但从编译器的角度来看,它只需要任何有效的语句。

于 2012-12-18T19:05:34.657 回答
1

该行为是大括号运算符的行为。它创建了一个变量范围,以及其他用途。它们可以省略,代码块就是下面这行。

for(int i = 0; i < 10; i++)
  foreach(blah in y)
    dosomething();

这是许多类 c 语言的特性。

于 2012-12-18T19:00:52.943 回答
1

using 后面跟着一个语句,一个块就是一个语句。因此,虽然通常在使用后你有一个块,但你可以有一个语句,在你的例子中是 while,然后,while 后面跟着一个块。

没有什么不寻常的。

于 2012-12-18T19:01:42.717 回答
1

在我看来,这个“概念”与允许以下内容的原则相同:

if(somethingTrue)
    when(somethingTrue)
       if(somethingTrue)
           // some code to be executed

即,单行“块”而不是括号内的多行。

于 2012-12-18T19:03:13.120 回答
1

您只需要在最后一次使用后包含括号

不要求最后一次使用 have { }。您的示例只是使用或不使用复合块嵌套语句的更一般能力的特例{ }

于 2012-12-18T19:05:03.143 回答