[C#] 왜 진술 (j ++)인가? 금지?

다음 코드가 잘못되었습니다 ( ideone 참조 ).

public class Test
{
    public static void Main()
    {
        int j = 5;
        (j++);      // if we remove the "(" and ")" then this compiles fine.
    }
}

오류 CS0201 : 할당, 호출, 증분, 감소, 대기 및 새 객체 표현식 만 명령문으로 사용할 수 있습니다.

  1. 괄호를 제거 할 때 코드가 컴파일되는 이유는 무엇입니까?
  2. 왜 괄호로 컴파일되지 않습니까?
  3. C #은 왜 그렇게 설계 되었습니까?


답변

깊은 통찰력에 감사드립니다.

최선을 다하겠습니다.

다른 답변에서 언급했듯이 컴파일러에서 표현식명령문 으로 사용되고 있음을 감지하고 있습니다. 많은 언어 (C, JavaScript 등)에서 표현식을 명령문으로 사용하는 것은 합법적입니다. 2 + 2;효력이없는 진술 임에도 불구하고 이러한 언어에서는 합법적입니다. 일부 표현식은 해당 값에만 유용하고 일부 표현식은 부작용 (예 : void returning method 호출)에만 유용하며 일부 표현식은 불행히도 두 가지 모두에 유용합니다. (증가처럼)

요점 : 표현만으로 구성되는 진술은 그 표현이 일반적으로 값보다 부작용에 더 유용한 것으로 생각되지 않는 한 거의 확실하게 오류 입니다. C # 디자이너는 일반적으로 부작용으로 간주되는 표현을 허용하고 일반적으로 가치에 유용한 것으로 간주되는 표현은 허용하지 않음으로써 중간 지점을 찾고자했습니다. C # 1.0에서 식별 한 식 집합은 증분, 감소, 메서드 호출, 할당 및 다소 논쟁의 여지가있는 생성자 호출이었습니다.


ASIDE : 일반적으로 대상의 구성은 구성의 부작용이 아닌 생성 된 값에 사용되는 것으로 생각합니다. 내 생각에 허용 new Foo();은 약간의 오해입니다. 특히, 실제 패턴에서 보안 결함을 일으키는이 패턴을 보았습니다.

catch(FooException ex) { new BarException(ex); } 

코드가 복잡하면이 결함을 발견하기가 놀랍게 어려울 수 있습니다.


따라서 컴파일러는 해당 목록에없는 표현식으로 구성된 모든 명령문을 감지합니다. 특히 괄호로 묶인 표현식은 괄호로 묶인 표현식으로 식별됩니다. “문 표현으로 허용됨”목록에 없으므로 허용되지 않습니다.

이 모든 것은 C # 언어의 디자인 원칙을 따르고 있습니다. 당신이 타이핑 (x++);했다면 당신은 아마 뭔가 잘못했을 것 입니다. 이것은 아마도 오타 M(x++);일 수도 있습니다. C # 컴파일러 팀 의 태도는 ” 이 작업을 수행 할 수있는 방법을 찾아 낼 수 있는가? ” 가 아니라는 점을 기억하십시오 . “C # 컴파일러 팀의 태도는” 유연한 코드가 실수 일 가능성이있는 경우개발자에게 알려주십시오. “입니다. C # 개발자는 그런 태도를 좋아합니다.

이제, C # 사양이 실제로 몇 가지 이상한 경우 가 있습니다. 의미 또는 괄호는 허용하지만 C # 컴파일러 어쨌든을 허용하는 명백한 것을 상태. 대부분의 경우 지정된 동작과 허용 된 동작 사이의 사소한 불일치는 완전히 무해하므로 컴파일러 작성자는 이러한 작은 버그를 수정 한 적이 없습니다. 당신은 그에 대해 읽을 수 있습니다 :

수익률 myVar와 수익률 (myVar)간에 차이가 있습니까?


답변

에서 C # 언어 사양

식 문은 식을 평가하는 데 사용됩니다. 명령문으로 사용할 수있는 표현식에는 메소드 호출, 새 연산자를 사용한 오브젝트 할당, =를 사용한 지정 및 복합 지정 연산자, ++ 및-연산자를 사용한 증분 및 감소 조작 및 식 대기가 포함됩니다.

명령문을 괄호로 묶으면 소위 괄호로 묶인 표현식이 새로 작성됩니다. 사양에서 :

괄호로 묶인 표현식은 괄호로 묶인 표현식으로 구성됩니다. … 괄호 안의 표현식을 평가하여 괄호 안의 표현식을 평가합니다. 괄호 안의 표현식이 네임 스페이스 또는 유형을 나타내는 경우 컴파일 타임 오류가 발생합니다. 그렇지 않으면 괄호로 묶은 표현식의 결과는 포함 된 표현식의 평가 결과입니다.

괄호로 묶은 표현식은 유효한 표현식 명령문으로 나열되지 않으므로 스펙에 따라 올바른 명령문이 아닙니다. 디자이너가 그것을 할 선택한 이유이 방법은 누구의 추측이지만 전체 문을 괄호에 포함되는 경우 괄호 유용한 일을하지 않기 때문에 내 건은 다음과 같습니다 stmt(stmt)정확히 동일합니다.


답변

주위에 괄호를 beacause i++ 는 표현식을 작성 / 정의하고 있습니다. 오류 메시지에서 알 수 있듯이 간단한 표현식은 명령문으로 사용할 수 없습니다.

왜 언어가 이런 식으로 설계 되었습니까? 코드처럼 오해를 일으키지 않는 문장으로 오해의 소지가있는 버그를 방지하기 위해

int j = 5;
j+1; 

두 번째 줄은 효과가 없습니다 (그러나 눈치 채지 못할 수도 있습니다). 그러나 컴파일러 대신 코드를 제거하는 대신 (코드가 필요하지 않기 때문에) 명시 적으로 코드를 제거하도록 요청하거나 무언가를 입력하지 않은 경우 수정해야합니다.

편집 :

c #의 대괄호 (캐스트 및 함수 호출과 같은 다른 용도 외에)는 표현식을 그룹화하고 단일 표현식 (하위 표현식 작성)을 리턴하는 데 사용됩니다.

그 코드 수준에서는 오직 stament 만 허용됩니다.

j++; is a valid statement because it produces side effects

근데 용감한 표현을 사용하면 표현으로 변합니다

myTempExpression = (j++)

myTempExpression;

컴파일러가 표현식을 부작용으로 확신 할 수 없기 때문에 유효하지 않습니다 (중지 문제가 발생하지 않는 한).


답변