5

Zauważyłem coś szczególnego w Visual Studio. Po pierwsze, spróbuj wpisać ten (C#) gdzieś w funkcji:Ostrzeżenie referencyjne programu Visual Studio - dlaczego nie wystąpił błąd?

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

Teraz, od razu będzie to oznaczać s w s.Length jako błąd, mówiąc: „Use of unassigned local variable 's'”. Z drugiej strony, spróbuj tego kodu:

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

To będzie kompilować i podkreślają s w private string s z ostrzeżeniem, mówiąc: „Field 'Foo.s' is never assigned to, and will always have its default value null”.

Teraz, jeśli VS jest tak inteligentny i wie, że s zawsze będzie miało wartość NULL, dlaczego nie jest błędem, aby uzyskać jego długość w drugim przykładzie? Moje pierwotne przypuszczenie brzmiało: "Daje tylko błąd kompilacji, jeśli kompilator po prostu nie może wykonać swojej pracy, ponieważ kod technicznie działa tak długo, jak długo nie wywołuje Bar(), to tylko ostrzeżenie." Tyle tylko, że pierwsze wyjaśnienie unieważnia wyjaśnienie. Nadal można uruchomić kod bez błędu, o ile nigdy nie wywołasz Bar(). Co daje? Tylko niedopatrzenie, czy coś mi brakuje?

Odpowiedz

8

Pierwszy przykład (błąd) jest przykładem śledzenia kompilatora definite-assignment i jest stosowany tylko do zmiennych lokalnych. Z powodu ograniczonego kontekstu kompilator ma hermetyczną przyczepność w tej sytuacji. Zauważ, że s nie ma wartości null, jest niezdefiniowane.

W drugim przykładzie s jest polem (i domyślnie ma wartość NULL). Nie ma błędu kompilatora, ale zawsze zostanie przechwycony w czasie wykonywania. Ten szczególny przypadek może zostać uwięziony, ale ten rodzaj błędu nie jest generalnie wykrywalny przez kompilator.
Na przykład można dodać metodę Bar2(), która przypisuje ciąg do s, ale wywołanie go później niż Bar(), lub w ogóle nie. To wyeliminowałoby ostrzeżenie, ale nie błąd wykonania.

Tak jest zgodnie z projektem.

0

Jedyne, co mogę zrobić, to to, że w drugim przykładzie s można zmienić poprzez odbicie (używając BindingFlags.Private, aby uzyskać dostęp do prywatnego członka).

0

W pierwszej próbce ów jest zmienna lokalna i kompilator może easialy sprawdzić, s varible nie został przydzielony zanim zostanie użyty.

W drugim s jest zmienną globalną i możliwe, że została zainicjowana gdzie indziej w klasie.

+0

s nie jest globalny, jest instancją -pole. –

3

Dla drugiego przykładu kod jest prawidłowy, może po prostu nie działać poprawnie. Oto kilka przypadków, w których ten program mógł wykonać "pomyślnie"

  • Kompilator nie jest w 100% poprawny. Możliwe jest, że "s" ma wartość inną niż null, jeśli instancja jest modyfikowana za pomocą odbicia.
  • Program można uruchomić bez błędu, jeśli metoda nie jest nigdy Bar nazywa
  • Ten program może być program testowy, który jest wyzwalanie NullReferenceException względów testowania
Powiązane problemy