Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

optional nesting? What is this language feature called, and is it intended?

Tags:

c#

I came across something interesting that I can't seem to find any more information on, or a proper name for.

I think most of us are aware that if you have multiple using blocks, you only need to include brackets after the last using:

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

However, goofing around I found that the following code also works, without brackets immediately following the using, piggybacking the while:

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

Does anyone know the name of this language "feature" that allows code block merging?

like image 617
overslacked Avatar asked Dec 18 '12 18:12

overslacked


People also ask

What do you mean by nesting of functions?

A nested function is a function that is completely contained within a parent function. Any function in a program file can include a nested function.

What does Optional mean in protobuf?

In proto3, all fields are "optional" (in that it is not an error if the sender fails to set them). But, fields are no longer "nullable", in that there's no way to tell the difference between a field being explicitly set to its default value vs. not having been set at all.

What is nesting of functions give an example?

The nested function's name is local to the block where it is defined. For example, here we define a nested function named square, and call it twice: foo (double a, double b) { double square (double z) { return z * z; } return square (a) + square (b); }

What is nesting of structure?

A nested structure in C is a structure within structure. One structure can be declared inside another structure in the same way structure members are declared inside a structure. Syntax: struct name_1.


1 Answers

Yes, this is intended. It is an idiom that C♯ inherits from C and C++. If you have a single statement enclosed in curly braces the braces are usually optional. Whether you use them or not is mostly an issue of style and readability. For nested using statements it's common to omit the braces for the outer layers.

Language grammar

In grammatical terms, a using block is followed by a statement. Usually this is a block statement, but it doesn't have to be.

There are a variety of kinds of statements. There are expression statements like a = b;. There are iteration statements like while (boolean-expression) { ... }. Here the entire while loop counts as a single statement. And there are block statements, which consist of one or more statements enclosed in curly braces.

See the C# Language Specification, Appendix C. Grammar, §C.2.5 Statements for a formal specification of statements:

statement:
    labeled-statement
    declaration-statement
    embedded-statement
embedded-statement:
    block
    empty-statement
    expression-statement
    selection-statement
    iteration-statement
    jump-statement
    try-statement
    checked-statement
    unchecked-statement
    lock-statement
    using-statement
block:
    
{ statement-listopt}

Usually the curly braces around statements can be omitted if you have a single statement. These are equivalent:

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

As are these:

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

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

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

Sometimes required

There are exceptions where curly braces are required. Method bodies must always have curly braces. It is baked into the grammar.

method-body:
    block
    
;

Similarly, try/catch/finally clauses must have curly braces. Same thing for checked and unchecked. You can see this in the grammar. A catch clause is defined as "catch block" rather than "catch statement".

try-statement:
    
try block catch-clauses
    
try block finally-clause
    
try block catch-clauses finally-clause
specific-catch-clause:
    
catch ( class-type identifieropt) block
general-catch-clause:
    
catch block
finally-clause:
    
finally block
checked-statement:
    
checked block
unchecked-statement:
    
unchecked block

Why is this? The short answer is it eliminates ambiguities in the grammar. For an in-depth explanation, see Eric Lippert's explanation of this inconsistency.

like image 167
John Kugelman Avatar answered Sep 30 '22 13:09

John Kugelman