C #에서 선행 문없이 {} 코드 블록을 허용하는 이유는 무엇입니까?


86

왜 C #을 허용 않는 앞의 문이없는 코드 블록 (예를 들어 if, else, for, while)?

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

70
하지 말아야 할 이유 있습니까?
Jamiec

30
그러나 답변에서 알 수 있듯이 그것은 단지 "아프지 않으므로 허용하자"는 것 이상의 의미를 가지고 있습니다. 이것이 바로 그런 질문의 요점입니다.
Seldon

8
한 질문은 무죄 충분 소리,하지만 대답은 정말 나에게 소중한 것을 가르쳐
Nicolas78

7
@Akash : 이유를 묻지 않고서는 결코 나아지지 않을 것입니다.
Richard

7
@Akash : 그것은 높은 수준의 엘리트 주의적 태도처럼 보입니다. 사람들은 항상 질문이 있고, 이유를 물어볼 이유가 없다면 SO를 갖는 것은 의미가 없습니다. 이 사이트는 사람들이 우리의 당면한 문제를 해결하도록하는 것이 아니라 우리 모두가 더 나은 프로그래머가되는 데 도움이 될 질문과 답변의 저장소를 제공합니다. 그래서 이유를 묻는 것입니다! :-)
리처드

답변:


90

당신이주는 맥락에서는 의미가 없습니다. 콘솔에 상수 문자열을 쓰는 것은 프로그램 흐름의 어느 곳에서나 동일한 방식으로 작동합니다. 1

대신, 일반적으로 일부 지역 변수의 범위를 제한하는 데 사용합니다. 이것은 여기여기에서 더 자세히 설명 됩니다 . 간단한 예 는 João Angelo의 답변Chris Wallis의 답변 을 참조하십시오. C 스타일 구문을 사용하는 다른 언어에도 똑같이 적용되지만이 질문과 관련이 있다는 것은 아닙니다.


1 물론, 전혀 예상치 못한 Console일을하는 Write()방법을 사용하여 재미 있고 자신 만의 수업을 만들기로 결정하지 않는 한 .


24
Re : 다른 언어 : 보통,하지만 항상 그런 것은 아닙니다. JavaScript는 주목할만한 예외입니다. 특정 블록에서 지역 변수를 선언하는 것은 변수의 범위를 블록으로 지정하지 않습니다.
Eric Lippert

@EricLippert : C #에서 블록 내에서 변수를 선언하면 런타임의 관점에서 변수 범위가 지정됩니까? 내가 알 수 있듯이 변수의 수명은 범위 지정 블록에 의해 제한되지 않는 경우가 많습니다. 루프에서 변수로 수행 한 첫 번째 작업이 out작성된 인터페이스 구현에 매개 변수로 전달하는 경우 혼합 언어 프로젝트에서 관찰 할 수있는 사실 입니다. 다른 언어로, 그 구현은 변수를 쓰기 전에 읽습니다.
supercat

그리고 C ++에서는 GC 대신 RAII 때문에 훨씬 더 유용합니다.
Deduplicator

C ++에서는 try / catch 블록처럼 작동하므로 해당 범위 내에서 선언 된 변수와 클래스는 해당 범위를 벗어날 때 스택에서 튀어 나옵니다. 이것은 이름 충돌을 방지하고 함수의 메모리 공간을 줄이는 데 도움이됩니다. 또한 코드 편집기의 자동 완성에서 해당 변수를 제거합니다. 종종 try / catch 블록이 더 유용하다고 생각합니다.
Kit10

144

{ ... }로컬 변수에 대한 새로운 범위의 도입 적어도 부작용을 갖는다.

나는 switch각 사례에 대해 다른 범위를 제공하기 위해 문 에서 사용하는 경향이 있으며, 이런 식으로 사용의 가능한 가장 가까운 위치에서 동일한 이름으로 지역 변수를 정의하고 사례 수준에서만 유효 함을 나타낼 수 있습니다.



6
케이스에 스코프가 필요한 경우 너무 큽니다! 추출 방법.
Jay Bazuzi

20
@Jay Bazuzi, 두 개 이상의 경우에 동일한 이름을 가진 지역 변수를 갖고 싶다고해서 그들이 거대해야한다는 의미는 아닙니다. 당신은 점프하고 거대한 :) ... 결론
주앙 안젤로

Great Answer 배지를 축하합니다! :)
BoltClock

1
@BoltClock, 감사합니다. {}금 배지를 계속 유지 하려면 몇 가지 질문이 더 필요합니다 ... :)
João Angelo

56

범위정의 하기 위해 중괄호를 사용하는 많은 C 구문 언어의 논리적 부작용 이라기보다는 C # 의 기능 이 아닙니다 .

귀하의 예에서 중괄호는 전혀 효과가 없지만 다음 코드에서는 변수의 범위와 가시성을 정의합니다.

이것은 i가 첫 번째 블록에서 범위를 벗어나고 다음 블록에서 다시 정의되기 때문에 허용 됩니다.

{
    {
        int i = 0;
    }

    {
        int i = 0;
    }
}

이 작업은 허용되지 않습니다 내가 범위 밖으로 떨어 더 이상 외부 범위에서 볼 수없는 것처럼 :

{
    {
        int i = 0;
    }

    i = 1;
}

기타 등등.


1
다양한 영어 풍미에서 괄호 명명법의 불일치에 대해 읽었지만 어떤 풍미가 {}괄호 로 알려져 있습니까?
BoltClock

좋은 질문! 10 년 전에 제 멘토가 제 두뇌에 심은 것 같아요. 나는 아마도 그들을 '중괄호'또는 '중괄호'라고 부를 것입니다. 각자 자신의 ... en.wikipedia.org/wiki/…
Chris Wallis

10
내 어휘에서 '('= 괄호, '{'= 중괄호, '['= 대괄호
pb.

잠시만 요, 나는 그들을 중괄호라고 부르고 Wikipedia에는 ​​그 이름이 포함되어 있습니다. Oxford English Dictionary는 이러한 대괄호 사용을 다음과 같이 정의합니다 One of two marks of the form [ ] or ( ), and in mathematical use also {}, used for enclosing a word or number of words, a portion of a mathematical formula, or the like, so as to separate it from the context; . 어쨌든 괄호는 아니지만 '중괄호'는 괜찮아 보입니다.
dumbledad

IME, "중괄호"및 "대괄호".
cp.engr

18

{}여러 문장을 포함 할 수있는 문장으로 생각 합니다.

하나의 문이 뒤에 오는 부울 식으로 존재하는 if 문을 고려하십시오 . 이것은 작동합니다.

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

이것은 잘 작동합니다.

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

내가 착각하지 않았다면 이것을 블록 문이라고합니다.

이후 {}다른 문을 포함 할 수 있습니다 또한 다른 포함 할 수 있습니다 {}. 변수의 범위는 부모 {}(블록 문)에 의해 정의됩니다 .

내가 말하려는 요점은 그것은 {}단지 진술 일 뿐이므로 if 또는 무엇이든 필요하지 않습니다.


+1 C 스타일 언어에서 중괄호는 소위 "복합 명령문"입니다.
Michael Ekstrand 2011-06-03

12

C- 구문 언어의 일반적인 규칙은 "그 사이의 모든 { }것은 단일 문으로 취급되어야하며 단일 문이 할 수있는 곳이면 어디든 갈 수 있습니다"입니다.

  • 애프터 if.
  • for, while또는 do.
  • 코드의 모든 곳 .

모든 의도와 목적을 위해 언어 문법에 다음이 포함되었습니다.

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

즉, "문은 (다양한 것) 또는 여는 중괄호 로 구성 될 수 있으며 , 그 뒤에 문 목록 (하나 이상의 문을 포함 할 수 있음)이 뒤 따르고 닫힌 중괄호가 뒤 따릅니다." IE " { }블록은 모든 문을 어디에서나 대체 할 수 있습니다". 코드 중간에 포함됩니다.

{ }단일 문이 갈 수있는 곳에 블록을 허용하지 않는 것은 실제로 언어 정의를 더 복잡 하게 만들었습니다 .


누군가가 (9 년 후)이 대답을 올렸는데, 이것은 실제로이 질문에 대한 구체적인 대답은 아니었지만 훨씬 더 일반적인 토론이었습니다. 언어와 도서관으로 대체 될 수 있을지 모르겠지만 .. 어쨌든 즐거웠습니다. 감사합니다.
Massimo

1

C ++ (및 Java)는 선행 문없이 코드 블록을 허용했기 때문입니다.

C가 허용했기 때문에 C ++에서 허용했습니다.

모든 것은 유럽 프로그램 언어 ( Modula-2 기반) 디자인이 아니라 미국 프로그램 언어 (C 기반) 디자인이 이겼다는 사실 때문이라고 말할 수 있습니다 .

(제어문은 단일 명령문에서 작동하며 명령문은 그룹이되어 새 명령문을 작성할 수 있습니다.)


Module2 또는 Modula2를 의미합니까?
Richard Ev

실제로 이것은 정답입니다. 또한 "모든 컴퓨터 언어가 그렇기 때문에"라고
Fattie


0

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;
    }
}

여기에 이미지 설명 입력


0

"왜"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

나는 이것이 각 구조 수준에 대한 방법을 사용하여 더 우아하게 해결할 수 있다는 것을 알고 있습니다. 그러나 다시 한 번, 샘플 데이터 시더와 같은 작업은 일반적으로 신속해야합니다.

따라서 위의 코드가 선형으로 실행 되더라도 코드 구조는 객체의 "실제"구조를 나타내므로 다른 개발자가 이해, 유지 및 확장하기가 더 쉽습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.