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.)
이는 i
for 루프 내부 의 범위가 for 루프 임을 의미합니다 . i
for-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);
}
여기서 실수의 가능성에 대해 생각해보십시오. 마지막으로 i
0이나 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 #의 규칙은 프로그래밍에있어 많은 시간이 필요하지 않지만 코드를 깨끗하고 읽기 쉽게 유지해야합니다.
예를 들어, 루프 후에 정의하면 괜찮지 만 코드를 읽고 정의 행을 놓친 사람은 루프 변수와 관련이 있다고 생각할 수 있습니다.