ProgramingTip

C # 변수 범위 지정 : 'x'는 'x'에 다른 의미를 부여 할 수 없습니다.

bestdevel 2020. 11. 18. 09:32
반응형

C # 변수 범위 지정 : 'x'는 'x'에 다른 의미를 부여 할 수 없습니다.


if(true)
{
    string var = "VAR";
}

string var = "New VAR!";

결과는 다음과 가변적입니다.

오류 1 'var'라는 이름의 지역 변수는 'var'에 다른 의미를 부여하기 때문에 범위에서 선언 할 수 없습니다. 이미 '하위'범위에서 다른 것을 나타냅니다.

아버지 지구가 부서지는 것은 없지만 명백한 잘못이 아닙니까? 동료 개발자와 저는 첫 번째 선언이 다른 범위에 있어야 할 것인지 궁금해서 두 번째 선언이 첫 번째 선언을 방해 할 수 없습니다.

C #이 두 범위를 구분할 수없는 이유는 무엇입니까? 첫 번째 IF 범위가 나머지 제거되지 않은 제거되지 않습니까?

외부에서 var를 호출 할 수있는 경우 첫 번째 var가 두 번째 범위와 관련이 없기 때문에 오류 메시지가 잘못되었습니다.


여기서 문제는 대체로 좋은 관행 중 하나이며 부주의 한 실수를 방지하는 것입니다. C # 컴파일러 는 이론적으로 범위간에 물론이고 여기서 설계 할 수 있습니다. 그러나 이것은 내가보기에 약간 이득을위한 많은 노력이 될 것이다.

var범위 부모 의 선언이 경우 문 앞에 있으면 해결할 수없는 명명 충돌이있을 수 있습니다. 컴파일러는 다음 두 경우를 구별하지 않습니다. 분석은 예상대로 선언 / 사용 순서가 아닌 범위를 기준으로 순전히 수행 됩니다.

이론적으로 허용되는 (그러나 C #에 관한 한 여전히 유효하지 않음) :

if(true)
{
    string var = "VAR";
}

string var = "New VAR!";

및 허용되지 않는 것 (부모 변수를 선언하므로) :

string var = "New VAR!";

if(true)
{
    string var = "VAR";
}

둘 다 변수와 범위에서 정확히 동일하게 취급됩니다.

자,이 시나리오에서 변수 중 하나에 다른 이름을 다수없는 실제 이유가 있습니까? 나는 당신의 실제 변수가 호출되지 않는다고 가정합니다 (희망) var. 여전히 동일한 변수 이름을 반복하려는 경우 형제 범위에 제안십시오.

if(true)
{
    string var = "VAR";
}

{
    string var = "New VAR!";
}

그러나 이것은 거의 모든 경우에 반대하는 것이 좋습니다.


명백한 명백한 잘못이 아닙니까?

아니요, 잘못된 것은 아닙니다. 이것은 C # 사양의 "단순 이름, 블록의 불변의 의미"섹션 7.5.2.1의 올바른 구현입니다.

사양은 다음과 가변합니다.


선언 또는 선언자에서 단순 이름으로 주어진 식별자의 각 발생에 대해 해당 발생의 지역 변수 선언 공간 내에서 또는 선언자에서 단순 이름과 동일한 식별자의 다른 모든 발생은 참조해야합니다. 실재. 이 규칙은 주어진 블록, 스위치 블록, for-, foreach- 또는 using-statement 또는 익명 함수 내에서 이름의 의미가 항상 동일합니다.


C #이 두 범위를 구분할 수없는 이유는 무엇입니까?

질문은 말도보기. 분명히 컴파일러 두 범위를 구별 할 수 있습니다. 가 두 범위 컴파일러를 구별 할 수 없다면 어떻게 오류가 발생할 수 있습니까? 오류 메시지 두 개의 다른 범위가 있다는 것입니다.

첫 번째 IF 범위가 나머지 제거되지 않은 제거되지 않습니까?

아니요. 조건 문의 결과로 블록 문에 의해 정의 된 범위 (및 지역 변수 선언 공간)는 어휘 적으로 메소드의 본문을 정의하는 외부 블록의 일부입니다. 따라서 외부 블록의 내용에 대한 규칙이 내부 블록의 내용에 적용됩니다.

외부에서 var를 호출 할 수있는 경우 첫 번째 var가 두 번째 범위와 관련이 없기 때문에 오류 메시지가 잘못되었습니다.

이것은 완전히 잘못된 것입니다. 지역 변수가 더 이상 존재하지 않기 때문에 외부 블록에 포함되지 않는다. 오류 메시지가 나타납니다.

여기서 오류는 변수의 범위가 다른 변수의 범위와 겹치는 지 여부와는 관련이 없습니다. 여기서 관련된 유일한 것은 블록 (외부 블록)이 모든 것입니다. 여기서는 동일한 단순한 이름이 완전히 다른 두 가지를 참조하는 데 사용됩니다. C # 간단한 이름이에서는 보기 처음 사용하는 블록 전체에서 하나의 의미를 가져야 합니다 .

예를 들면 :

class C 
{
    int x;
    void M()
    { 
        int x = 123;
    }
}

그것은 완벽하게 합법적입니다. 외부 x의 범위가 내부 x의 범위와 겹치지 만 오류는 아닙니다. 오류는 무엇입니까?

class C 
{
    int x;
    void M()
    { 
        Console.WriteLine(x);
        if (whatever)
        {
            int x = 123;
        }
    }
}

이제 단순한 이름 "x"는 M의 본문 내부에있는 두 가지 다른 것을 의미하기 때문입니다. "this.x"와 지역 변수 "x"를 의미합니다. 같은 단순한 이름 이 같은 블록에서 완전히 다른 두 가지를 의미하는 것은 개발자와 코드 유지 관리자에게 혼란 스럽기 때문에 불법입니다.

우리는 병렬 블록이 두 가지 다른 방식으로 사용되는 동일한 단순 이름을 포함하도록 허용합니다. 이것은 합법적입니다.

class C 
{
    int x;
    void M()
    { 
        if (whatever)
        {
            Console.WriteLine(x);
        }
        if (somethingelse)
        {
            int x = 123;
        }
    }
}

이제 두 개의 일관 되지 않은 x 사용을 포함하는 유일한 블록은 외부 블록이고 해당 블록에는 "x"사용을 직접 포함 하지 않고 간접적으로 만 포함됩니다 .


이것은 C ++에서 유효하지만 많은 버그와 잠 못 이루는 밤의 소스입니다. 저는 C # 사람들이 경고 / 오류를 던지는 것이 더 낫다고 생각합니다. 대부분의 경우 코더가 실제로 원하는 것보다 버그이기 때문입니다.

여기에 '이 오류가 나오는 사양의 어떤 부분에 흥미로운 토론을이야.

편집 (일부 예) -----

C ++에서 다음은 유효합니다 (외부 선언이 내부 범위 이전인지 이후인지 여부는 실제로 중요하지 않으며 이전이면 더 흥미롭고 버그가 발생하기 쉽습니다).

void foo(int a)
{
    int count = 0;
    for(int i = 0; i < a; ++i)
    {
        int count *= i;
    }
    return count;
}

이제 함수가 몇 줄 더 길고 오류를 발견하지 못할 수도 있다고 상상해보십시오. 컴파일러는 불평하지 않으며 (예전에는 아니고 C ++의 최신 버전에 대해 확신하지 못함) 함수는 항상 0을 반환합니다.

behaivour는 분명히 버그이므로 C ++-lint 프로그램이나 컴파일러가 이것을 지적하면 좋을 것입니다. 버그가 아니라면 내부 변수의 이름을 바꾸면 쉽게 해결할 수 있습니다.

부상에 대한 모욕을 더하기 위해 GCC와 VS6이 for 루프의 카운터 변수가 속한 위치에 대해 서로 다른 의견을 가지고 있음을 기억합니다. 하나는 그것이 외부 범위에 속하고 다른 하나는 그렇지 않다고 말했습니다. 크로스 플랫폼 코드에서 작업하는 것은 약간 짜증납니다. 내 라인 수를 유지하는 또 다른 예를 들겠습니다.

for(int i = 0; i < 1000; ++i)
{
    if(array[i] > 100)
        break;
}

printf("The first very large value in the array exists at %d\n", i);

이 코드는 GCC가 아닌 VS6 IIRC에서 작동했습니다. 어쨌든 C #은 몇 가지를 정리했습니다.

참고 URL : https://stackoverflow.com/questions/2049330/c-sharp-variable-scoping-x-cannot-be-declared-in-this-scope-because-it-would

반응형