Aktualizowanie bazy kodu przy użyciu typów odwołań dopuszczanych do wartości null w celu ulepszenia ostrzeżeń diagnostycznych o wartości null

Typy referencyjne dopuszczane do wartości null umożliwiają deklarowanie, czy zmienne typu odwołania powinny lub nie powinny mieć przypisanej null wartości. Analiza statyczna i ostrzeżenia kompilatora, gdy kod może wyłuszczyć null , jest najważniejszą zaletą tej funkcji. Po włączeniu kompilator generuje ostrzeżenia, które pomagają uniknąć zgłaszania System.NullReferenceException błędu podczas uruchamiania kodu.

Jeśli baza kodu jest stosunkowo mała, możesz włączyć funkcję w projekcie, ostrzeżenia dotyczące adresów i korzystać z zalet ulepszonej diagnostyki. Większe bazy kodu mogą wymagać bardziej ustrukturyzowanego podejścia do rozwiązywania ostrzeżeń w miarę upływu czasu, włączając tę funkcję w miarę adresowania ostrzeżeń w różnych typach lub plikach. W tym artykule opisano różne strategie aktualizowania bazy kodu i kompromisów związanych z tymi strategiami. Przed rozpoczęciem migracji zapoznaj się z koncepcyjnym omówieniem typów referencyjnych dopuszczanych do wartości null. Obejmuje ona statyczną analizę kompilatora, wartości stanu null o wartości może mieć wartość null, a nie null oraz adnotacje dopuszczane do wartości null. Po zapoznaniu się z tymi pojęciami i terminami możesz przystąpić do migracji kodu.

Zaplanuj migrację

Niezależnie od sposobu aktualizowania bazy kodu celem jest włączenie ostrzeżeń dopuszczających wartość null i adnotacji dopuszczających wartość null w projekcie. Po osiągnięciu tego celu będziesz mieć <nullable>Enable</nullable> ustawienie w projekcie. Do dostosowywania ustawień w innym miejscu nie będzie potrzebna żadna z dyrektyw preprocesora.

Pierwszym wyborem jest ustawienie domyślne dla projektu. Dostępne są następujące opcje:

  1. Wyłączenie dopuszczane do wartości null jako domyślne: wyłączenie jest wartością domyślnąNullable, jeśli nie dodasz elementu do pliku projektu. Użyj tej wartości domyślnej, jeśli nie dodajesz aktywnie nowych plików do bazy kodu. Głównym działaniem jest zaktualizowanie biblioteki tak, aby korzystała z typów odwołań dopuszczanych do wartości null. Użycie tej wartości domyślnej oznacza dodanie dyrektywy preprocesora dopuszczającego wartość null do każdego pliku podczas aktualizowania jego kodu.
  2. Włącz wartość null jako wartość domyślną: ustaw tę wartość domyślną, gdy aktywnie opracowujesz nowe funkcje. Chcesz, aby wszystkie nowe kod korzystały z typów odwołań dopuszczanych do wartości null i analizy statycznej dopuszczanej do wartości null. Użycie tej wartości domyślnej oznacza, że musisz dodać element #nullable disable na początku każdego pliku. Te dyrektywy preprocesora zostaną usunięte podczas rozwiązywania problemów z ostrzeżeniami w każdym pliku.
  3. Ostrzeżenia dopuszczające wartość null jako domyślne: wybierz tę wartość domyślną dla migracji dwufazowej. W pierwszej fazie ostrzeżenia dotyczące adresów. W drugiej fazie włącz adnotacje do deklarowania oczekiwanego stanu null zmiennej. Użycie tej wartości domyślnej oznacza, że musisz dodać element #nullable disable na początku każdego pliku.
  4. Adnotacje dopuszczane do wartości null jako domyślne. Dodaj adnotację do kodu przed skierowaniem ostrzeżeń.

Włączenie wartości null, ponieważ ustawienie domyślne powoduje zwiększenie pracy z góry w celu dodania dyrektyw preprocesora do każdego pliku. Zaletą jest to, że każdy nowy plik kodu dodany do projektu będzie włączony z możliwością dopuszczania wartości null. Każda nowa praca będzie uwzględniać wartość null; należy zaktualizować tylko istniejący kod. Wyłączenie wartości null, ponieważ domyślne działanie jest lepsze, jeśli biblioteka jest stabilna, a głównym celem programowania jest przyjęcie typów referencyjnych dopuszczających wartość null. W miarę dodawania adnotacji do interfejsów API włącza się typy referencyjne dopuszczane do wartości null. Po zakończeniu włączysz typy odwołań dopuszczane do wartości null dla całego projektu. Podczas tworzenia nowego pliku należy dodać dyrektywy preprocesora i poinformować go o wartości null. Jeśli jakikolwiek deweloperzy w zespole zapominają, że nowy kod znajduje się teraz na liście prac, aby wszystkie kody dopuszczały wartość null.

Które z tych strategii wybierasz zależy od tego, ile aktywnych programowania ma miejsce w projekcie. Tym bardziej dojrzały i stabilny projekt, tym lepiej jest druga strategia. Tym więcej funkcji jest opracowywanych, tym lepiej jest pierwszą strategię.

Ważne

Globalny kontekst dopuszczania wartości null nie ma zastosowania do wygenerowanych plików kodu. W ramach każdej strategii kontekst dopuszczalny do wartości null jest wyłączony dla dowolnego pliku źródłowego oznaczonego jako wygenerowany. Oznacza to, że wszystkie interfejsy API w wygenerowanych plikach nie są adnotacjami. Istnieją cztery sposoby oznaczania pliku jako wygenerowanego:

  1. W pliku .editorconfig określ generated_code = true w sekcji, która ma zastosowanie do tego pliku.
  2. Umieść <auto-generated> lub <auto-generated/> w komentarzu w górnej części pliku. Może on znajdować się w dowolnym wierszu w tym komentarzu, ale blok komentarza musi być pierwszym elementem w pliku.
  3. Uruchom nazwę pliku przy użyciu TemporaryGeneratedFile_
  4. Zakończ nazwę pliku .designer.cs, .generated.cs, .g.cs lub .g.i.cs.

Generatory mogą korzystać z #nullable dyrektywy preprocesora.

Omówienie kontekstów i ostrzeżeń

Włączanie ostrzeżeń i adnotacji kontroluje sposób, w jaki typy odwołań widoków kompilatora i możliwość dopuszczania wartości null. Każdy typ ma jedną z trzech wartości null:

  • nieświadomy: wszystkie typy odwołań są bezwartościowe, gdy kontekst adnotacji jest wyłączony.
  • nonnullable: Nienaznotowany typ C odwołania jest niemożliwy do po włączeniu kontekstu adnotacji.
  • nullable: typ odwołania z adnotacjami, C?, jest dopuszczany do wartości null, ale może zostać wyświetlone ostrzeżenie, gdy kontekst adnotacji jest wyłączony. Zmienne zadeklarowane za pomocą var parametru są dopuszczane do wartości null, gdy kontekst adnotacji jest włączony.

Kompilator generuje ostrzeżenia na podstawie tej wartości null:

  • typy nienaliwalne powodują ostrzeżenia, jeśli do nich jest przypisana potencjalna null wartość.
  • Typy dopuszczające wartość null powodują ostrzeżenia, jeśli zostaną wyłuszone, gdy wartość może mieć wartość null.
  • Typy nieświadome powodują ostrzeżenia, jeśli są wyłuszczene, gdy jest włączona opcja być może-null , a kontekst ostrzeżenia jest włączony.

Każda zmienna ma domyślny stan dopuszczający wartość null, która zależy od jego wartości null:

  • Zmienne dopuszczane do wartości null mają domyślny stan null może mieć wartość null.
  • Zmienne bez wartości null mają domyślny stannull not-null.
  • Zmienne niezwiązane z wartością null mają domyślny stannull not-null.

Przed włączeniem typów odwołań dopuszczanych do wartości null wszystkie deklaracje w bazie kodu są nieświadome wartości null. Jest to ważne, ponieważ oznacza to, że wszystkie typy odwołań mają domyślny stannull not-null.

Ostrzeżenia dotyczące adresów

Jeśli projekt korzysta z platformy Entity Framework Core, przeczytaj wskazówki dotyczące pracy z typami referencyjnymi dopuszczanymi do wartości null.

Po rozpoczęciu migracji należy zacząć od włączenia tylko ostrzeżeń. Wszystkie deklaracje pozostają nieświadome wartości null, ale po wyłuszczeniu wartości po zmianie stanu null na być może-null zostaną wyświetlone ostrzeżenia. W miarę rozwiązywania tych ostrzeżeń będziesz sprawdzać wartość null w większej liczniejszych lokalizacjach, a baza kodu staje się bardziej odporna. Aby poznać konkretne techniki w różnych sytuacjach, zobacz artykuł Techniki rozwiązywania problemów z ostrzeżeniami dopuszczanymi do wartości null.

Przed kontynuowaniem pracy z innym kodem możesz rozwiązać ostrzeżenia i włączyć adnotacje w każdym pliku lub klasie. Jednak często wydajniejsze jest rozwiązanie problemów z ostrzeżeniami wygenerowanymi, gdy kontekst zawiera ostrzeżenia przed włączeniem adnotacji typu. W ten sposób wszystkie typy są nieświadome , dopóki nie zostanie rozwiązany pierwszy zestaw ostrzeżeń.

Włączanie adnotacji typu

Po adresowaniu pierwszego zestawu ostrzeżeń można włączyć kontekst adnotacji. Spowoduje to zmianę typów odwołań od nieświadomych do niemożliwych do wprowadzania zmian. Wszystkie zadeklarowane zmienne z parametrem var mają wartość null. Ta zmiana często wprowadza nowe ostrzeżenia. Pierwszym krokiem w rozwiązywaniu problemów z ostrzeżeniami kompilatora jest użycie ? adnotacji dla parametrów i zwracania typów w celu wskazania, kiedy argumenty lub zwracane wartości mogą mieć wartość null. W miarę wykonywania tego zadania twoim celem nie jest tylko naprawienie ostrzeżeń. Ważniejsze jest, aby kompilator zrozumiał intencję potencjalnych wartości null.

Atrybuty rozszerzają adnotacje typów

Dodano kilka atrybutów w celu wyrażenia dodatkowych informacji o stanie null zmiennych. Reguły interfejsów API są prawdopodobnie bardziej skomplikowane niż nie null lub być może null dla wszystkich parametrów i zwracanych wartości. Wiele interfejsów API ma bardziej złożone reguły, jeśli zmienne mogą lub nie mogą mieć nullwartości . W takich przypadkach użyjesz atrybutów, aby wyrazić te reguły. Atrybuty opisujące semantyka interfejsu API znajdują się w artykule Dotyczącym atrybutów, które mają wpływ na analizę dopuszczającą wartość null.

Następne kroki

Po usunięciu wszystkich ostrzeżeń po włączeniu adnotacji można ustawić domyślny kontekst dla projektu tak, aby był włączony. Jeśli dodano jakiekolwiek pragmas w kodzie dla adnotacji dopuszczalnej wartości null lub kontekstu ostrzeżenia, możesz je usunąć. W czasie mogą pojawić się nowe ostrzeżenia. Możesz napisać kod wprowadzający ostrzeżenia. Zależność biblioteki może zostać zaktualizowana dla typów odwołań dopuszczanych do wartości null. Te aktualizacje spowodują zmianę typów w tej bibliotece z dopuszczających wartość null na niezniszalną lub dopuszczającą wartość null.

Możesz również zapoznać się z tymi pojęciami w naszym module Learn dotyczącym bezpieczeństwa dopuszczanego do wartości null w języku C#.