[C#] for-loop에 선언 된 변수는 지역 변수입니까?

C #을 오랫동안 사용해 왔지만 다음을 깨달은 적이 없습니다.

 public static void Main()
 {
     for (int i = 0; i < 5; i++)
     {

     }

     int i = 4;  //cannot declare as 'i' is declared in child scope                
     int A = i;  //cannot assign as 'i' does not exist in this context
 }

그렇다면이 이름으로 변수를 선언 할 수 없다면 for 블록 외부에서 ‘i’값을 사용할 수없는 이유는 무엇입니까?

for-loop가 사용하는 반복자 변수는 해당 범위에서만 유효하다고 생각했습니다.



답변

for-loop 외부 및 for-loop 외부에서 동일한 이름의 변수를 정의 할 수없는 이유는 외부 범위의 변수가 내부 범위에서 유효하기 때문입니다. 이것이 허용된다면 for-loop 내에 두 개의 ‘i’변수가 있음을 의미합니다.

보다: MSDN 범위

구체적으로 특별히:

local-variable-declaration (8.5.1 절)에 선언 된 지역 변수의 범위는 선언이 발생하는 블록입니다.

for 문의 초기화에 대해 선언 된 지역 변수의 범위 (섹션 8.8.3)는 초기화 장치, for 조건, for-iterator 및 for 문의 포함 명령문입니다.

또한 지역 변수 선언 (C # 사양의 섹션 8.5.1)

구체적으로 특별히:

local-variable-declaration에 선언 된 로컬 변수의 범위는 선언이 발생하는 블록입니다. 로컬 변수의 로컬 변수 선언 앞에있는 텍스트 위치에서 로컬 변수를 참조하면 오류가 발생합니다. 지역 변수의 범위 내에서 다른 지역 변수 나 상수를 같은 이름으로 선언하는 것은 컴파일 타임 오류입니다.

(Emphasis mine.)

이는 ifor 루프 내부 의 범위가 for 루프 임을 의미합니다 . ifor-loop 외부의 범위 는 전체 주요 방법 for-loop입니다. 의미하는 것은 두 번 나타납니다i 는 위와 같이 유효하지 않은 루프 내부에 한다는 입니다.

허용되지 않는 이유 는 루프 내에서만 사용할 수 int A = i;있기 때문 int i입니다 for. 따라서 더 이상 외부에서 액세스 할 수 없습니다for 루프 .

보시다시피이 두 가지 문제는 범위를 벗어난 결과입니다. 첫 번째 문제 ( int i = 4;)는 루프 범위 i내 에서 두 개의 변수를 생성합니다 for. 이므로int A = i; 범위를 벗어난 변수에 액세스 할 수 있습니다.

대신 할 수있는 i것은 전체 메소드에 범위가 지정되어 선언 하고 메소드와 for 루프 범위 모두에서 사용하는 것입니다. 이렇게하면 규칙을 어 기지 않아도됩니다.

public static void Main()
{
    int i;

    for (i = 0; i < 5; i++)
    {

    }

    // 'i' is only declared in the method scope now, 
    // no longer in the child scope -> valid.
    i = 4;

    // 'i' is declared in the method's scope -> valid. 
    int A = i;
}

편집 :

물론 C # 컴파일러는이 코드가 상당히 유효하게 컴파일되도록 변경 될 수 있습니다. 결국 이것은 유효합니다 :

for (int i = 0; i < 5; i++)
{
    Console.WriteLine(i);
}

for (int i = 5; i > 0; i--)
{
    Console.WriteLine(i);
}

그러나 코드 가독성 및 유지 관리가 다음과 같은 코드를 작성할 수 있다면 실제로 도움이 될 것입니다.

public static void Main()
{
    int i = 4;

    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine(i);
    }

    for (int i = 5; i > 0; i--)
    {
        Console.WriteLine(i);
    }

    Console.WriteLine(i);
}

여기서 실수의 가능성에 대해 생각해보십시오. 마지막으로 i0이나 4를 인쇄합니까? 이제 이것은 매우 작은 예입니다. 추적하기 쉽고 추적하기 쉽지만 외부 i이름을 다른 이름으로 선언 한 것보다 유지 관리가 쉽고 읽기 쉽습니다 .

NB :

C #의 범위 지정 규칙은 C ++ 의 범위 지정 규칙과 다릅니다 . C ++에서 변수는 선언 된 위치부터 블록 끝까지 범위 내에 있습니다. C ++에서 코드를 유효한 구조로 만듭니다.


답변

J.Kommer의 대답은 정확 : 지역 변수가 선언 될 때까지 잠시, 그것은 불법 지역 변수 선언 공간이 겹치는 다른 지역 변수 선언 공간에 같은 이름의 지역이있다.

여기에 위반되는 추가 C # 규칙이 있습니다. 추가 규칙은 간단한 이름을 사용하여 서로 다른 두 개의 중첩 로컬 변수 선언 공간 내에서 두 개의 다른 엔티티를 참조하는 것은 불법입니다. 따라서 귀하의 모범은 불법 일뿐만 아니라 불법이기도합니다.

class C
{
    int x;
    void M()
    {
        int y = x;
        if(whatever)
        {
            int x = 123;

“y”라는 로컬 변수 선언 공간에서 “x”라는 간단한 이름이 사용되어 “this.x”와 로컬 “x”라는 두 가지 다른 의미를 갖습니다.

이러한 문제에 대한 자세한 분석은 http://blogs.msdn.com/b/ericlippert/archive/tags/simple+names/ 를 참조하십시오 .


답변

i루프 후 메소드 내부 를 선언하고 사용 하는 방법이 있습니다.

static void Main()
{
    for (int i = 0; i < 5; i++)
    {

    }

    {
        int i = 4;
        int A = i;
    }
}

Java 로이 작업을 수행 할 수 있습니다 (C에서 유래 할 수는 없습니다). 물론 변수 이름 때문에 약간 지저분합니다.


답변

루프 i 전에 선언 했다면 for루프 내에서 선언하는 것이 여전히 유효해야한다고 생각합니까?

아니요, 두 범위가 겹치기 때문입니다.

할 수없는 대해서는 int A=i;때문에, 물론 그것은 단순히입니다 i만이 존재 for루프가해야처럼.


답변

J.Kommer의 답변 외에도 (+1 btw). NET 범위의 표준에는 다음이 있습니다.

블록 If 문과 같은 블록 구조 내에서 변수를 선언하면 해당 변수의 범위는 블록 끝까지 만됩니다. 수명은 절차가 끝날 때까지입니다.

프로 시저 프로 시저 내에서 If 문 외부에서 변수를 선언하면 범위는 End Sub 또는 End Function까지입니다. 변수의 수명은 절차가 끝날 때까지입니다.

따라서 for 루프 헤더 내에서 decalared int는 for 루프 블록 중에 만 범위에 속 하지만 수명은 Main()코드가 완료 될 때까지 지속됩니다 .


답변

이것을 생각하는 가장 쉬운 방법은 I의 외부 선언을 루프 위로 옮기는 것입니다. 그때 분명 해져야합니다.

어느 쪽이든 같은 범위이므로 수행 할 수 없습니다.


답변

또한 C #의 규칙은 프로그래밍에있어 많은 시간이 필요하지 않지만 코드를 깨끗하고 읽기 쉽게 유지해야합니다.

예를 들어, 루프 후에 정의하면 괜찮지 만 코드를 읽고 정의 행을 놓친 사람은 루프 변수와 관련이 있다고 생각할 수 있습니다.