Rozszerzenie odpowiedzi Marka, inicjowanie zmiennej lokalnej jest również związane z procesem weryfikacji .
Interfejs CLI wymaga, aby w każdym możliwym do zweryfikowania kodzie (tj. Moduły, które nie zostały jawnie poproszone o pominięcie procesu weryfikacji przy użyciu właściwości SkipVerfication z atrybutu SecurityPermission), wszystkie lokalne zmienne muszą zostać zainicjowane przed ich użyciem. Nieprzestrzeganie tego spowoduje zgłoszenie VerficationException.
Co ciekawsze, kompilator automatycznie dodaje flagę .locals init
do każdej metody wykorzystującej zmienne lokalne. Ta flaga powoduje, że kompilator JIT generuje kod, który inicjuje wszystkie zmienne lokalne do ich wartości domyślnych. To znaczy, mimo że już zainicjowałeś je we własnym kodzie, JIT będzie zgodny z flagą .locals init
i wygeneruje odpowiedni kod inicjujący. Ta "zduplikowana inicjalizacja" nie ma wpływu na wydajność, ponieważ w konfiguracjach, które umożliwiają optymalizacje, kompilator JIT wykryje duplikację i skutecznie potraktuje ją jako "martwy kod" (automatycznie wygenerowana procedura inicjalizacji nie pojawi się w wygenerowanych instrukcjach asemblera).
Według Microsoftu (również poparte przez Erica Lipperta w odpowiedzi na pytanie na jego blogu), w większości przypadków, gdy programiści nie inicjują zmiennej lokalnej, nie robią tego, ponieważ przekazują na podstawowym środowiskiem do zainicjowania ich zmiennej, aby były wartościami domyślnymi, ale tylko dlatego, że "zapomniały", powodując czasami iluzoryczne błędy logiczne.
Aby zmniejszyć prawdopodobieństwo występowania błędów tego typu w kodzie C#, kompilator wciąż nalega, aby zainicjować zmienne lokalne. Nawet jeśli dodamy flagę .locals init
do wygenerowanego kodu IL.
Bardziej wyczerpujące wyjaśnienie na ten temat można znaleźć tutaj: Behind The .locals init Flag
To tylko powtarzając pytanie. Ale dlaczego? –
@YairHalberstadt zależy od tego, czy "dlaczego?" oznacza regułę lub przyczynę reguły. Odpowiedziałem na pierwszy, który prawdopodobnie odpowiada na pytanie; dla drugiego: ponieważ do czasu, gdy rozważyłeś łańcuchy konstruktorów, metody wirtualne wywoływane podczas budowy oraz fakt, że na poziomie IL konstruktorzy bazowi mogą być wywoływani w dowolnym punkcie łańcucha wywoływania - prawie niemożliwe jest wypowiedzenie sensible o inicjalizacji pola; jednakowo, pola mogą się pokrywać, co czyni jeszcze ważniejszym zerowanie przestrzeni, więc nie jest wymagany technicznie init - kontrast ... –
@YairHalberstadt zmienne lokalne, które mają bardzo łatwe sprawdzanie przydziału, gdzie niezainicjowane zwykle oznaczają błąd i gdzie może pominąć zerowanie (chociaż obecny czas wykonywania nigdy nie ma, IIRC). –