web-dev-qa-db-ja.com

C#では、前のステートメントなしで{}コードブロックが許可されるのはなぜですか?

C#で、前のステートメントなしでコードブロックが許可されるのはなぜですか(例:ifelseforwhile)?

void Main()
{
    {   // any sense in this?
        Console.Write("foo");
    }
}
84
Seldon

あなたが与える文脈では、意味はありません。コンソールへの定数文字列の書き込みは、プログラムフローのどこでも同じように機能します。1

代わりに、通常、それらを使用して一部のローカル変数のスコープを制限します。これについては、さらに詳しく説明します here および here 。簡単な例については、 JoãoAngeloの回答 および Chris Wallisの回答 を参照してください。同じことがCスタイルの構文を持つ他のいくつかの言語にも当てはまると思いますが、この質問には関係ありません。


1もちろん、面白くないようにして、まったく予期しないことを行うWrite()メソッドを使用して、独自のConsoleクラスを作成することを決定した場合を除きます。

88
BoltClock

{ ... }には、少なくともローカル変数の新しいスコープを導入するという副作用があります。

私はそれらをswitchステートメントで使用して、ケースごとに異なるスコープを提供する傾向があり、このようにして、使用可能な最も近い場所で同じ名前のローカル変数を定義し、それらがケースレベルで有効です。

142
João Angelo

C#の機能ではなく、中かっこを使用してスコープを定義する多くのC構文言語の論理的な副作用スコープの定義

あなたの例では、中かっこはまったく効果がありませんが、次のコードでは、変数のスコープ、つまり可視性を定義しています。

これは許可されていますです。これは、最初のブロックのスコープから外れ、次のブロックで再び定義されるためです。

{
    {
        int i = 0;
    }

    {
        int i = 0;
    }
}

これは許可されていません iがスコープ外になり、外側のスコープに表示されなくなったためです。

{
    {
        int i = 0;
    }

    i = 1;
}

などなど。

55
Chris Wallis

{}は、いくつかのステートメントを含むことができるステートメントと見なします。

oneステートメントが後に続くブール式の外に存在するifステートメントについて考えます。これはうまくいくでしょう:

if (true) Console.Write("FooBar");

これも機能します:

if (true)
{
  Console.Write("Foo");
  Console.Write("Bar");
}

私が間違っていない場合、これはブロックステートメントと呼ばれます。

{}には他のステートメントを含めることができるため、他の{}を含めることもできます。変数のスコープは、その親の{}(ブロックステートメント)によって定義されます。

私が作ろうとしている点は、{}は単なるステートメントであるため、ifまたは何も必要としないということです...

17
RBaarda

C構文言語の一般的な規則は、「{ }の間のすべてのものは単一のステートメントとして扱われるべきであり、単一のステートメントが可能な場所ならどこにでも行くことができる」です。

  • ifの後。
  • forwhileまたはdoの後。
  • コード内の任意の場所

すべての意図と目的のために、言語文法には次のものが含まれています。

     <statement> :== <definition of valid statement> | "{" <statement-list> "}"
<statement-list> :== <statement> | <statement-list> <statement>

つまり、「ステートメントは(さまざまなもの)または開始中かっこで構成され、その後にステートメントリスト(1つ以上のステートメントが含まれる場合があります)、閉じた中かっこで構成されます」。 I.E. 「{ }ブロックは、任意のステートメントをどこにでも置き換えることができます」。コードの途中に含めます。

{ }ブロックを1つのステートメントで実行できる場所に許可しないと、実際には言語定義がより複雑になります。

11
Massimo

C++(およびJava)は、前のステートメントなしでコードブロックを許可したためです。

Cがそうしたので、C++はそれらを許可しました。

ヨーロッパのプログラム言語( Modula-2 ベース)のデザインではなく、アメリカのプログラム言語(Cベース)のデザインが勝ったという事実にすべて起因すると言えます。

(制御ステートメントは単一のステートメントに作用します。ステートメントはグループになり、新しいステートメントを作成できます)

1
Ian Ringrose
// if (a == b)
// if (a != b)
{
    // do something
}
1
user202448

「なぜ」C#は前のステートメントなしでコードブロックを許可するのかと尋ねました。 「なぜ」という質問は、「この構成の利点として何が考えられるか」と解釈することもできます。

個人的に、私はC#でステートメントのないコードブロックを使用しています。コードブロックはローカル変数のスコープを制限することに留意しながら、他の開発者にとっては読みやすさが大幅に改善されています。たとえば、次のコードスニペットを考えてみます。これは、追加のコードブロックのおかげで非常に読みやすくなっています。

OrgUnit world = new OrgUnit() { Name = "World" };
{
    OrgUnit europe = new OrgUnit() { Name = "Europe" };
    world.SubUnits.Add(europe);
    {
        OrgUnit germany = new OrgUnit() { Name = "Germany" };
        europe.SubUnits.Add(germany);

        //...etc.
    }
}
//...commit structure to DB here

これは、各構造レベルのメソッドを使用することで、よりエレガントに解決できることを知っています。ただし、サンプルデータシーダーなどは通常、高速である必要があることに注意してください。

したがって、上記のコードは直線的に実行されますが、コード構造はオブジェクトの「実際の」構造を表すため、他の開発者が理解、維持、および拡張しやすくなります。

0
Marco

1 ...ステートメントのスコープ領域を維持するため..または関数、これは大きなコードを管理するのに非常に役立ちます。

{
    {
        // Here this 'i' is we can use for this scope only and out side of this scope we can't get this 'i' variable.

        int i = 0;
    }

    {
        int i = 0;
    }
}

enter image description here

0
Raj