5

저는 Visual Studio 특유의 것을 발견했습니다. 첫째, 어딘가 기능이 (C#)를 입력 해보십시오 :Visual Studio null 참조 경고 - 왜 오류가 없습니까?

class Foo 
{ 
    public void Bar() 
    { 
     string s; 
     int i = s.Length; 
    } 
} 

을 이제 바로는 "Use of unassigned local variable 's'"을 말하는 오류로 s.Length에서 s을 표시합니다.

class Foo 
{ 
    private string s; 
    public void Bar() 
    { 
     int i = s.Length; 
    } 
} 

그것은 컴파일하고, "Field 'Foo.s' is never assigned to, and will always have its default value null"을 말하고, 경고와 함께 private string s에서 s을 강조 : 다른 한편으로,이 코드를 사용해보십시오.

이제 VS가 똑똑하고 s가 항상 null임을 알면 두 번째 예제에서 길이를 얻는 것이 오류가 아닌 이유는 무엇입니까? 원래 컴파일러가 작업을 완료 할 수 없으면 컴파일 오류 만 발생합니다. Bar()를 호출하지 않는 한 코드가 기술적으로 실행되기 때문에 이는 경고 일뿐입니다. " 단, 첫 번째 예에서는 설명이 무효화됩니다. Bar()를 호출하지 않는 한 오류없이 코드를 실행할 수 있습니다. 그래서 무엇을 제공합니까? 그냥 감시하거나 뭔가 놓친 거니?

답변

8

첫 번째 예 (오류)는 컴파일러의 definite-assignment 추적의 예이며 로컬 변수에만 적용됩니다. 제한된 컨텍스트로 인해 컴파일러는 이러한 상황을 완벽하게 파악합니다. s은 null이 아니므로 정의되지 않습니다.

두 번째 예에서 s은 필드이며 기본값은 null입니다. 컴파일러 오류는 없지만 런타임에 항상 catch됩니다. 이 특별한 경우는 함정에 빠질 수 있지만 이러한 종류의 오류는 일반적으로 컴파일러에서 감지 할 수 없습니다.
예를 들어 s에 문자열을 할당하지만 Bar()보다 나중에 호출하거나 전혀 호출하지 않는 방법 Bar2()을 추가 할 수 있습니다. 그러면 경고는 제거되지만 런타임 오류는 제거되지 않습니다.

의도적으로 설계된 동작입니다.

0

내가 할 수있는 유일한 추측은 두 번째 예제에서 리플렉션 (BindingFlags.Private를 사용하여 전용 멤버에 액세스)을 통해 변경할 수 있다는 것입니다. 첫번째 샘플의 에서

0

로컬 변수 및 컴파일러 easialy가 사용되기 전에 S varible가 할당되지 않았 음을 확인할 수있다.

두 번째 설명에서 s은 전역 변수이며 클래스의 다른 곳에서 초기화되었을 수 있습니다.

+0

의, 그것은 인스턴스 글로벌되어 있지 않으며 테스트 이유로는 NullReferenceException을 유발하는 테스트 프로그램이 될 수 -들. –

3

두 번째 예제의 경우 코드가 올바르지 만 제대로 실행되지 않을 수 있습니다. 이 프로그램이 "성공적으로"실행할 수있는 몇 가지 사례가 있습니다

  • 컴파일러가 100 % 올바르지 않습니다. 리플렉션을 통해 인스턴스가 수정되면 "s"는 null이 아닌 값을 가질 수 있습니다. 메소드 바 이제까지
  • 을 호출되지 않은 경우
  • 이 프로그램은 오류없이 실행할 수있는이 프로그램은
관련 문제