Typy referencyjne dopuszczające wartość null
W kontekście nieświadomym wartości null wszystkie typy odwołań były dopuszczane do wartości null. Typy odwołań dopuszczające wartość null odwołują się do grupy funkcji włączonej w kontekście obsługującym wartość null, które minimalizują prawdopodobieństwo, że kod powoduje, że środowisko uruchomieniowe zgłasza błąd System.NullReferenceException. Typy referencyjne dopuszczające wartość null obejmują trzy funkcje, które ułatwiają uniknięcie tych wyjątków, w tym możliwość jawnego oznaczania typu odwołania jako dopuszczanego do wartości null:
- Ulepszona analiza przepływu statycznego, która określa, czy zmienna może być
null
przed jego wyłuszczeniem. - Atrybuty, które dodają adnotacje do interfejsów API, aby analiza przepływu określała stan null.
- Adnotacje zmiennych używane przez deweloperów do jawnego deklarowania zamierzonego stanu null dla zmiennej.
Analiza stanu null i adnotacje zmiennych są domyślnie wyłączone dla istniejących projektów — co oznacza, że wszystkie typy odwołań nadal mogą mieć wartość null. Począwszy od platformy .NET 6, są one domyślnie włączone dla nowych projektów. Aby uzyskać informacje na temat włączania tych funkcji przez deklarowanie kontekstu adnotacji dopuszczającego wartość null, zobacz Konteksty dopuszczające wartość null.
W pozostałej części tego artykułu opisano sposób działania tych trzech obszarów funkcji w celu wygenerowania ostrzeżeń, gdy kod może zostać wyłuszczyćnull
wartość. Dereferencing zmiennej oznacza dostęp do jednego z jego elementów członkowskich przy użyciu .
operatora (kropka), jak pokazano w poniższym przykładzie:
string message = "Hello, World!";
int length = message.Length; // dereferencing "message"
W przypadku wyłudzenia zmiennej, której wartość to null
, środowisko uruchomieniowe zgłasza wartość System.NullReferenceException.
Możesz również zapoznać się z tymi pojęciami w naszym module Learn dotyczącym bezpieczeństwa z możliwością wartości null w języku C#.
Analiza stanu null
Analiza stanunull śledzi stan null odwołań. Ta analiza statyczna emituje ostrzeżenia, gdy kod może wymykać null
się . Te ostrzeżenia można rozwiązać, aby zminimalizować częstość występowania, gdy środowisko uruchomieniowe zgłasza błąd System.NullReferenceException. Kompilator używa analizy statycznej do określenia stanu null zmiennej. Zmienna nie ma wartości null lub może ma wartość null. Kompilator określa, że zmienna nie ma wartości null na dwa sposoby:
- Zmienna została przypisana do wartości, która jest znana jako nie null.
- Zmienna została sprawdzona względem
null
elementu i nie została zmodyfikowana od tego sprawdzenia.
Każda zmienna, która nie została określona przez kompilator jako wartość not-null , jest uznawana za może-null. Analiza zawiera ostrzeżenia w sytuacjach, w których można przypadkowo wyłusić null
wartość. Kompilator generuje ostrzeżenia na podstawie stanu null.
- Jeśli zmienna nie ma wartości null, ta zmienna może być bezpiecznie wyłuszona.
- Gdy zmienna ma wartość może mieć wartość null, ta zmienna musi zostać sprawdzona, aby upewnić się, że nie
null
jest ona wcześniej wyłuszczana.
Rozpatrzmy następujący przykład:
string message = null;
// warning: dereference null.
Console.WriteLine($"The length of the message is {message.Length}");
var originalMessage = message;
message = "Hello, World!";
// No warning. Analysis determined "message" is not null.
Console.WriteLine($"The length of the message is {message.Length}");
// warning!
Console.WriteLine(originalMessage.Length);
W poprzednim przykładzie kompilator określa, że message
jest to być może null po wydrukowaniu pierwszego komunikatu. Nie ma ostrzeżenia dla drugiego komunikatu. Końcowy wiersz kodu generuje ostrzeżenie, ponieważ originalMessage
może mieć wartość null. W poniższym przykładzie przedstawiono bardziej praktyczne zastosowanie przechodzenia drzewa węzłów do katalogu głównego, przetwarzania każdego węzła podczas przechodzenia:
void FindRoot(Node node, Action<Node> processNode)
{
for (var current = node; current != null; current = current.Parent)
{
processNode(current);
}
}
Poprzedni kod nie generuje żadnych ostrzeżeń dotyczących wyłudania zmiennej current
. Analiza statyczna określa, że current
nigdy nie jest wyłudzonych, gdy jest to być może null. Zmienna current
jest sprawdzana przed current.Parent
null
uzyskaniem dostępu i przed przekazaniem current
ProcessNode
do akcji. W poprzednich przykładach pokazano, jak kompilator określa stan null dla zmiennych lokalnych podczas inicjowania, przypisywania lub porównywania z null
.
Analiza stanu null nie śledzi wywoływanych metod. W rezultacie pola zainicjowane w typowej metodzie pomocnika wywoływanej przez konstruktory będą generować ostrzeżenie z następującym szablonem:
Właściwość bez wartości null "name" musi zawierać wartość inną niż null podczas zamykania konstruktora.
Te ostrzeżenia można rozwiązać na jeden z dwóch sposobów: Łańcuch konstruktorów lub atrybuty dopuszczające wartość null w metodzie pomocnika. Poniższy kod przedstawia przykład każdego z nich. Klasa Person
używa wspólnego konstruktora wywoływanego przez wszystkie inne konstruktory. Klasa Student
ma metodę pomocnika z adnotacją z atrybutem System.Diagnostics.CodeAnalysis.MemberNotNullAttribute :
using System.Diagnostics.CodeAnalysis;
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public Person() : this("John", "Doe") { }
}
public class Student : Person
{
public string Major { get; set; }
public Student(string firstName, string lastName, string major)
: base(firstName, lastName)
{
SetMajor(major);
}
public Student(string firstName, string lastName) :
base(firstName, lastName)
{
SetMajor();
}
public Student()
{
SetMajor();
}
[MemberNotNull(nameof(Major))]
private void SetMajor(string? major = default)
{
Major = major ?? "Undeclared";
}
}
Uwaga
W języku C# 10 dodano szereg ulepszeń analizy określonego przypisania i stanu null. Podczas uaktualniania do języka C# 10 można znaleźć mniej ostrzeżeń dopuszczających wartość null, które są fałszywie dodatnie. Więcej informacji o ulepszeniach specyfikacji funkcji można dowiedzieć się więcej na temat określonych ulepszeń przypisania.
Analiza stanu dopuszczającego wartość null i ostrzeżenia generowane przez kompilator pomagają uniknąć błędów programu przez wyłudzenie null
. Artykuł dotyczący rozwiązywania ostrzeżeń dopuszczających wartość null zawiera techniki poprawiania ostrzeżeń, które prawdopodobnie zobaczysz w kodzie.
Atrybuty podpisów interfejsu API
Analiza stanu null wymaga wskazówek od deweloperów, aby zrozumieć semantyka interfejsów API. Niektóre interfejsy API zapewniają sprawdzanie wartości null i powinny zmienić stan null zmiennej z być może null na nie null. Inne interfejsy API zwracają wyrażenia, które nie mają wartości null lub może null , w zależności od stanu null argumentów wejściowych. Rozważmy na przykład następujący kod, który wyświetla komunikat:
public void PrintMessage(string message)
{
if (!string.IsNullOrWhiteSpace(message))
{
Console.WriteLine($"{DateTime.Now}: {message}");
}
}
Na podstawie inspekcji każdy deweloper rozważy ten kod jako bezpieczny i nie powinien generować ostrzeżeń. Kompilator nie wie, że IsNullOrWhiteSpace
zapewnia sprawdzanie wartości null. Atrybuty są stosowane do informowania kompilatora, który message
nie ma wartości null , jeśli i tylko wtedy, gdy IsNullOrWhiteSpace
zwraca wartość false
. W poprzednim przykładzie podpis zawiera wartość , NotNullWhen
aby wskazać stan null :message
public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string message);
Atrybuty zawierają szczegółowe informacje na temat stanu null argumentów, zwracanych wartości i elementów członkowskich wystąpienia obiektu używanego do wywoływania elementu członkowskiego. Szczegółowe informacje na temat każdego atrybutu można znaleźć w artykule referencyjnym języka dotyczącym atrybutów referencyjnych dopuszczanych do wartości null. Wszystkie interfejsy API środowiska uruchomieniowego platformy .NET zostały oznaczone adnotacjami na platformie .NET 5. Możesz ulepszyć analizę statyczną przez dodawanie adnotacji do interfejsów API w celu udostępnienia semantycznych informacji o stanie null argumentów i zwracanych wartościach.
Adnotacje zmiennej dopuszczanej do wartości null
Analiza stanu null zapewnia niezawodną analizę większości zmiennych. Kompilator potrzebuje więcej informacji na temat zmiennych członkowskich. Kompilator nie może założyć założeń dotyczących kolejności uzyskiwania dostępu do publicznych elementów członkowskich. Dostęp do każdego publicznego członka można uzyskać w dowolnej kolejności. Dowolny z dostępnych konstruktorów może służyć do inicjowania obiektu. Jeśli pole składowe może kiedykolwiek zostać ustawione na null
wartość , kompilator musi założyć, że jego stan null ma wartość może mieć wartość null na początku każdej metody.
Można użyć adnotacji, które mogą zadeklarować, czy zmienna jest typem odwołania dopuszczalnym do wartości null , czy typem odwołania bez wartości null. Te adnotacje tworzą ważne instrukcje dotyczące stanu null dla zmiennych:
- Odwołanie nie ma mieć wartości null. Domyślny stan zmiennej referencyjnej nienależącej do wartości null. Kompilator wymusza reguły, które zapewniają, że bezpieczne jest wyłudzenie tych zmiennych bez uprzedniego sprawdzenia, czy nie ma wartości null:
- Zmienna musi zostać zainicjowana do wartości innej niż null.
- Zmienna nigdy nie może być przypisana do wartości
null
. Kompilator wystawia ostrzeżenie, gdy kod przypisuje wyrażenie może null do zmiennej, która nie powinna mieć wartości null.
- Odwołanie może mieć wartość null. Domyślnym stanem zmiennej referencyjnej dopuszczanej do wartości null jest być może null. Kompilator wymusza reguły, aby upewnić się, że prawidłowo sprawdzono
null
odwołanie:- Zmienna może zostać wyłuszona tylko wtedy, gdy kompilator może zagwarantować, że wartość nie
null
jest . - Te zmienne mogą być inicjowane z wartością domyślną
null
i mogą być przypisane do wartościnull
w innym kodzie. - Kompilator nie wyświetla ostrzeżeń, gdy kod przypisuje wyrażenie może mieć wartość null do zmiennej, która może mieć wartość null.
- Zmienna może zostać wyłuszona tylko wtedy, gdy kompilator może zagwarantować, że wartość nie
Każda zmienna referencyjna, która nie ma mieć null
stanu null, nie ma wartości null. Każda zmienna referencyjna, która początkowo może mieć null
stan nullmoże mieć wartość null.
Typ odwołania dopuszczalny do wartości null jest zanotowany przy użyciu tej samej składni co typy wartości dopuszczającej wartość null: jest ?
dołączany do typu zmiennej. Na przykład następująca deklaracja zmiennej zmiennej reprezentuje zmienną ciągu dopuszczaną do wartości null: name
string? name;
Każda zmienna, w ?
której nie jest dołączana do nazwy typu, jest typem referencyjnym bez wartości null. Obejmuje to wszystkie zmienne typu odwołania w istniejącym kodzie po włączeniu tej funkcji. Jednak wszelkie niejawnie wpisane zmienne lokalne (zadeklarowane przy użyciu var
) są typami referencyjnymi dopuszczanymi wartości null. Jak pokazano w poprzednich sekcjach, analiza statyczna określa stan null zmiennych lokalnych, aby określić, czy są one być może null.
Czasami należy zastąpić ostrzeżenie, gdy wiadomo, że zmienna nie ma wartości null, ale kompilator określa jego stan null może mieć wartość null. Użyj operatora !
forgiving o wartości null po nazwie zmiennej, aby wymusić, że stan nullnie ma wartości null. Jeśli na przykład wiesz, że zmienna name
nie null
jest, ale kompilator wystawia ostrzeżenie, możesz napisać następujący kod, aby zastąpić analizę kompilatora:
name!.Length;
Typy odwołań dopuszczające wartość null i typy wartości dopuszczających wartość null zapewniają podobną koncepcję semantyczną: zmienna może reprezentować wartość lub obiekt albo może to być null
zmienna . Jednak typy referencyjne dopuszczane do wartości null i typy wartości dopuszczanych do wartości null są implementowane inaczej: typy wartości dopuszczalnych wartości null są implementowane przy użyciu , System.Nullable<T>a typy odwołań dopuszczane do wartości null są implementowane przez atrybuty odczytywane przez kompilator. Na przykład string?
i string
są reprezentowane przez ten sam typ: System.String. int?
Jednak wartości i int
są reprezentowane odpowiednio przez System.Nullable<System.Int32>
elementy i System.Int32.
Typy referencyjne dopuszczane do wartości null to funkcja czasu kompilacji. Oznacza to, że obiekty wywołujące mogą ignorować ostrzeżenia, celowo użyć null
jako argumentu metody oczekującej odwołania innego niż null. Autorzy bibliotek powinni uwzględnić kontrole środowiska uruchomieniowego pod kątem wartości argumentów o wartości null. Jest to preferowana ArgumentNullException.ThrowIfNull opcja sprawdzania parametru względem wartości null w czasie wykonywania.
Ważne
Włączenie adnotacji dopuszczających wartość null może zmienić sposób określania, w jaki sposób platforma Entity Framework Core określa, czy element członkowski danych jest wymagany. Więcej szczegółów można znaleźć w artykule Entity Framework Core Fundamentals: Working with Nullable Reference Types (Podstawy platformy Entity Framework: praca z typami referencyjnymi dopuszczanymi wartości null).
Typy ogólne
Typy ogólne wymagają szczegółowych reguł do obsługi T?
dla dowolnego parametru T
typu . Reguły są koniecznie szczegółowe ze względu na historię i inną implementację dla typu wartości dopuszczanej do wartości null i typu odwołania dopuszczanego do wartości null. Typy wartości dopuszczalnych wartości null są implementowane przy użyciu System.Nullable<T> struktury . Typy referencyjne dopuszczające wartość null są implementowane jako adnotacje typów, które udostępniają reguły semantyczne kompilatorowi.
- Jeśli argument typu dla
T
jest typem referencyjnym,T?
odwołuje się do odpowiedniego typu odwołania dopuszczanego do wartości null. Jeśli na przykład element mastring
wartośćT
, wartośćT?
tostring?
. - Jeśli argument type dla
T
jest typem wartości,T?
odwołuje się do tego samego typu wartości,T
. Jeśli na przykładT
element toint
, elementT?
jest również .int
- Jeśli argument typu dla
T
jest typu odwołania dopuszczające wartość null,T?
odwołuje się do tego samego typu odwołania dopuszczające wartość null. Na przykład jeśli element tostring?
, elementT?
jest również wartościąstring?
.T
- Jeśli argument typu dla
T
jest typem wartości dopuszczanej do wartości null,T?
odwołuje się do tego samego typu wartości dopuszczających wartość null. Na przykład jeśli element toint?
, elementT?
jest również wartościąint?
.T
W przypadku zwracanych wartości T?
jest równoważne [MaybeNull]T
wartościom ; dla wartości T?
argumentów jest równoważne .[AllowNull]T
Aby uzyskać więcej informacji, zobacz artykuł Atrybuty analizy stanu null w dokumentacji języka.
Możesz określić różne zachowanie przy użyciu ograniczeń:
- Ograniczenie
class
oznacza, żeT
musi to być typ odwołania nie dopuszczający wartości null (na przykładstring
). Kompilator generuje ostrzeżenie, jeśli używasz typu odwołania dopuszczającego wartość null, takiego jakstring?
dla elementuT
. - Ograniczenie
class?
oznacza, żeT
musi być typem odwołania, innym niż null (string
) lub typem odwołania dopuszczanym do wartości null (na przykładstring?
). Gdy parametr typu jest typem odwołania dopuszczalnym do wartości null, takim jakstring?
, wyrażenieT?
odwołań, które to samo typu odwołania dopuszczające wartość null, takie jakstring?
. - Ograniczenie
notnull
oznacza, żeT
musi być typem referencyjnym bez wartości null lub typem wartości innej niż null. Jeśli używasz typu odwołania dopuszczającego wartość null lub typu wartości dopuszczanej do wartości null dla parametru typu, kompilator generuje ostrzeżenie. Ponadto, gdyT
jest typem wartości, zwracana wartość jest tym typem wartości, a nie odpowiadającym mu typem wartości dopuszczanej do wartości null.
Te ograniczenia pomagają uzyskać więcej informacji do kompilatora na temat sposobu T
użycia. Pomaga to, gdy deweloperzy wybierają typ dla T
, i zapewnia lepszą analizę stanu null , gdy jest używane wystąpienie typu ogólnego.
Konteksty dopuszczane do wartości null
Nowe funkcje chroniące przed zgłaszaniem elementu System.NullReferenceException mogą być destrukcyjne po włączeniu w istniejącej bazie kodu:
- Wszystkie jawnie wpisane zmienne referencyjne są interpretowane jako typy referencyjne, które nie dopuszczają wartości null.
- Znaczenie
class
ograniczenia w rodzajach ogólnych zmieniło się na oznaczające typ odwołania niepustego. - Nowe ostrzeżenia są generowane z powodu tych nowych reguł.
Musisz jawnie wyrazić zgodę na korzystanie z tych funkcji w istniejących projektach. Zapewnia to ścieżkę migracji i zachowuje zgodność z poprzednimi wersjami. Konteksty dopuszczane do wartości null umożliwiają precyzyjne sterowanie sposobem interpretowania zmiennych typu odwołania przez kompilator. Kontekst adnotacji dopuszczającego wartość null określa zachowanie kompilatora. Istnieją cztery wartości kontekstu adnotacji dopuszczanej do wartości null:
- disable: kod jest nieznośny bez wartości null.
- Ostrzeżenia dopuszczające wartość null są wyłączone.
- Wszystkie zmienne typu odwołania są typami referencyjnymi dopuszczanymi wartości null.
- Nie można zadeklarować zmiennej jako typu odwołania dopuszczanego do wartości null przy użyciu sufiksu
?
w typie. - Możesz użyć operatora forgiving o wartości null ,
!
ale nie ma żadnego efektu.
- enable: kompilator włącza wszystkie analizy odwołań o wartości null i wszystkie funkcje języka.
- Wszystkie nowe ostrzeżenia dopuszczające wartość null są włączone.
- Możesz użyć sufiksu
?
, aby zadeklarować typ odwołania dopuszczalny do wartości null. - Wszystkie inne zmienne typu odwołania są typami referencyjnymi, które nie dopuszczają wartości null.
- Operator forgiving o wartości null pomija ostrzeżenia dotyczące możliwego przypisania do elementu
null
.
- ostrzeżenia: kompilator wykonuje wszystkie analizy wartości null i emituje ostrzeżenia, gdy kod może wyłuszczyć wartość
null
.- Wszystkie nowe ostrzeżenia dopuszczające wartość null są włączone.
- Użycie sufiksu w
?
celu zadeklarowania typu odwołania dopuszczanego do wartości null powoduje ostrzeżenie. - Wszystkie zmienne typu odwołania mogą mieć wartość null. Jednak składowe mają stan nullnot-null dla otwierającego nawiasu klamrowego wszystkich metod, chyba że zadeklarowane z sufiksem
?
. - Można użyć operatora forgiving o wartości null,
!
.
- adnotacje: kompilator nie wykonuje analizy wartości null ani nie emituje ostrzeżeń, gdy kod może wyłuszczyć wartość
null
.- Wszystkie nowe ostrzeżenia dopuszczające wartość null są wyłączone.
- Możesz użyć sufiksu
?
, aby zadeklarować typ odwołania dopuszczalny do wartości null. - Wszystkie inne zmienne typu odwołania są typami referencyjnymi, które nie dopuszczają wartości null.
- Możesz użyć operatora forgiving o wartości null ,
!
ale nie ma żadnego efektu.
Kontekst adnotacji dopuszczający wartość null i kontekst ostrzeżenia dopuszczający wartość null można ustawić dla projektu przy użyciu <Nullable>
elementu w pliku csproj . Ten element konfiguruje sposób, w jaki kompilator interpretuje wartość null typów i jakie ostrzeżenia są emitowane. W poniższej tabeli przedstawiono dozwolone wartości i podsumowano określone konteksty.
Kontekst | Ostrzeżenia dotyczące wyłudzenia | Ostrzeżenia dotyczące przypisania | Typy odwołań | ? Sufiks |
! Operator |
---|---|---|---|---|---|
disable |
Disabled | Disabled | Wszystkie są dopuszczane do wartości null | Nie można użyć | Nie ma wpływu |
enable |
Enabled (Włączony) | Enabled (Włączony) | Bez wartości null, chyba że zadeklarowane za pomocą polecenia ? |
Deklaruje typ dopuszczalny do wartości null | Pomija ostrzeżenia dotyczące możliwego null przypisania |
warnings |
Enabled (Włączony) | Nie dotyczy | Wszystkie są dopuszczane do wartości null, ale elementy członkowskie są uważane za nie null przy otwieraniu nawiasu klamrowego metod | Tworzy ostrzeżenie | Pomija ostrzeżenia dotyczące możliwego null przypisania |
annotations |
Disabled | Disabled | Bez wartości null, chyba że zadeklarowane za pomocą polecenia ? |
Deklaruje typ dopuszczalny do wartości null | Nie ma wpływu |
Zmienne typu odwołania w kodzie skompilowanym w kontekście wyłączonym są nieświadome wartości null. Możesz przypisać literał lub zmienną null
o wartości może mieć wartość null do zmiennej, która nie jest nieświadoma wartości null. Jednak domyślny stan zmiennej o wartości null nie ma wartości null.
Możesz wybrać, które ustawienie jest najlepsze dla projektu:
- Wybierz opcję wyłącz dla starszych projektów, których nie chcesz aktualizować na podstawie diagnostyki ani nowych funkcji.
- Wybierz ostrzeżenia, aby określić, gdzie może zostać zgłoszony System.NullReferenceExceptionkod. Te ostrzeżenia można rozwiązać przed zmodyfikowaniem kodu w celu włączenia typów odwołań, które nie dopuszczają wartości null.
- Wybierz adnotacje , aby wyrazić intencję projektu przed włączeniem ostrzeżeń.
- Wybierz opcję Włącz dla nowych projektów i aktywnych projektów, w których chcesz chronić przed wyjątkami odwołania o wartości null.
Przykład:
<Nullable>enable</Nullable>
Można również użyć dyrektyw, aby ustawić te same konteksty w dowolnym miejscu w kodzie źródłowym. Są one najbardziej przydatne podczas migrowania dużej bazy kodu.
#nullable enable
: ustawia kontekst adnotacji dopuszczający wartość null i kontekst ostrzeżenia dopuszczający wartość null, aby włączyć.#nullable disable
: ustawia kontekst adnotacji dopuszczający wartość null i kontekst ostrzeżenia dopuszczający wartość null, aby wyłączyć.#nullable restore
: przywraca kontekst adnotacji dopuszczający wartość null i kontekst ostrzeżenia dopuszczający wartość null do ustawień projektu.#nullable disable warnings
: ustaw kontekst ostrzeżenia dopuszczający wartość null, aby wyłączyć.#nullable enable warnings
: ustaw kontekst ostrzeżenia dopuszczający wartość null, aby włączyć.#nullable restore warnings
: przywraca kontekst ostrzeżenia dopuszczający wartość null do ustawień projektu.#nullable disable annotations
: Ustaw kontekst adnotacji dopuszczalnej wartości null, aby wyłączyć.#nullable enable annotations
: Ustaw kontekst adnotacji dopuszczalnej wartości null, aby włączyć.#nullable restore annotations
: przywraca kontekst ostrzeżenia adnotacji do ustawień projektu.
Dla dowolnego wiersza kodu można ustawić dowolną z następujących kombinacji:
Kontekst ostrzeżenia | Kontekst adnotacji | Zastosowanie |
---|---|---|
domyślna wartość projektu | domyślna wartość projektu | Domyślny |
Włącz | Wyłącz | Rozwiązywanie problemów z ostrzeżeniami analizy |
Włącz | domyślna wartość projektu | Rozwiązywanie problemów z ostrzeżeniami analizy |
domyślna wartość projektu | Włącz | Dodawanie adnotacji typu |
Włącz | Włącz | Kod został już zmigrowany |
Wyłącz | Włącz | Dodawanie adnotacji do kodu przed naprawieniem ostrzeżeń |
Wyłącz | Wyłącz | Dodawanie starszego kodu do zmigrowanego projektu |
domyślna wartość projektu | Wyłącz | Rzadko |
Wyłącz | domyślna wartość projektu | Rzadko |
Te dziewięć kombinacji zapewnia szczegółową kontrolę nad diagnostyką, którą kompilator emituje dla kodu. Możesz włączyć więcej funkcji w dowolnym obszarze, który jest aktualizowany, bez wyświetlania dodatkowych ostrzeżeń, które nie są jeszcze gotowe do rozwiązania.
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:
- W pliku .editorconfig określ
generated_code = true
w sekcji, która ma zastosowanie do tego pliku. - 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. - Uruchamianie nazwy pliku przy użyciu TemporaryGeneratedFile_
- Zakończ nazwę pliku na . designer.cs, .generated.cs, .g.cs lub .g.i.cs.
Generatory mogą korzystać z #nullable
dyrektywy preprocesora.
Domyślnie konteksty adnotacji dopuszczające wartość null i ostrzeżenia są wyłączone. Oznacza to, że istniejący kod jest kompilowany bez zmian i bez generowania nowych ostrzeżeń. Począwszy od platformy .NET 6, nowe projekty zawierają <Nullable>enable</Nullable>
element we wszystkich szablonach projektów.
Te opcje zapewniają dwie odrębne strategie aktualizacji istniejącej bazy kodu w celu używania typów referencyjnych dopuszczanych wartości null.
Znane pułapki
Tablice i struktury zawierające typy referencyjne są znanymi pułapkami w odwołaniach dopuszczających wartość null i analizą statyczną, która określa bezpieczeństwo wartości null. W obu sytuacjach odwołanie nie dopuszczające wartości null może zostać zainicjowane do null
elementu bez generowania ostrzeżeń.
Struktury
Struktura, która zawiera typy referencyjne, które nie dopuszczają wartości null, umożliwia przypisywanie default
jej bez żadnych ostrzeżeń. Rozpatrzmy następujący przykład:
using System;
#nullable enable
public struct Student
{
public string FirstName;
public string? MiddleName;
public string LastName;
}
public static class Program
{
public static void PrintStudent(Student student)
{
Console.WriteLine($"First name: {student.FirstName.ToUpper()}");
Console.WriteLine($"Middle name: {student.MiddleName?.ToUpper()}");
Console.WriteLine($"Last name: {student.LastName.ToUpper()}");
}
public static void Main() => PrintStudent(default);
}
W poprzednim przykładzie nie ma ostrzeżenia PrintStudent(default)
, podczas gdy typy FirstName
odwołań nie dopuszczające wartości null i LastName
mają wartość null.
Innym bardziej typowym przypadkiem jest sytuacja, w której zajmujesz się strukturami ogólnymi. Rozpatrzmy następujący przykład:
#nullable enable
public struct Foo<T>
{
public T Bar { get; set; }
}
public static class Program
{
public static void Main()
{
string s = default(Foo<string>).Bar;
}
}
W poprzednim przykładzie właściwość Bar
będzie znajdować null
się w czasie wykonywania i jest przypisana do ciągu bez wartości null bez żadnych ostrzeżeń.
Tablice
Tablice są również znanym pułapem w typach referencyjnych dopuszczanych do wartości null. Rozważmy następujący przykład, który nie generuje żadnych ostrzeżeń:
using System;
#nullable enable
public static class Program
{
public static void Main()
{
string[] values = new string[10];
string s = values[0];
Console.WriteLine(s.ToUpper());
}
}
W poprzednim przykładzie deklaracja tablicy pokazuje, że zawiera ciągi niepuste, a jego elementy są inicjowane na null
wartość . Następnie zmienna s
ma przypisaną null
wartość (pierwszy element tablicy). Na koniec zmienna s
jest wyłuszczana, powodując wyjątek środowiska uruchomieniowego.
Zobacz też
- Propozycja typów referencyjnych dopuszczanych wartości null
- Wersja robocza specyfikacji typów referencyjnych dopuszczanych do wartości null
- Adnotacje parametrów typu nieograniczonego
- Samouczek wprowadzający do odwołań dopuszczanych do wartości null
- Dopuszczana wartość null (opcja kompilatora języka C#)