Udostępnij za pośrednictwem


Rozwiązywanie ostrzeżeń o wartości null

Celem ostrzeżeń dopuszczających wartość null jest zminimalizowanie prawdopodobieństwa, że aplikacja zgłosi błąd System.NullReferenceException po uruchomieniu. Aby osiągnąć ten cel, kompilator używa analizy statycznej i generuje ostrzeżenia, kiedy twój kod zawiera konstrukcje, które mogą prowadzić do wyjątków null. Kompilator udostępnia informacje dotyczące analizy statycznej, stosując adnotacje i atrybuty typu. Te adnotacje i atrybuty opisują nullowalność argumentów, parametrów i elementów członkowskich twoich typów. W tym artykule poznasz różne techniki radzenia sobie z ostrzeżeniami o wartości null generowanymi przez kompilator na podstawie analizy statycznej. Opisane tutaj techniki dotyczą ogólnego kodu języka C#. Dowiedz się, jak pracować z typami referencyjnymi dopuszczającymi wartość null oraz Entity Framework Core w Praca z typami referencyjnymi dopuszczającymi wartość null.

Typy odwołań dopuszczające wartości null, w tym operatory ? i !, są dozwolone tylko wtedy, gdy kontekst dopuszczający wartości null jest ustawiony na enable lub annotations. Można ustawić kontekst domyślnej wartości null, korzystając z opcji kompilatora Nullable w pliku projektu lub z pragmy #nullable w kodzie źródłowym.

W tym artykule omówiono następujące ostrzeżenia kompilatora:

  • CS8597 - Rzucana wartość może być null.
  • CS8598 - Operator tłumienia nie jest dozwolony w tym kontekście
  • CS8600 - Konwertowanie literału null lub możliwej wartości null na typ niepusty.
  • CS8601 - Możliwe przypisanie wartości null.
  • CS8602 - Dereference możliwego odwołania o wartości null.
  • CS8603 - Możliwy zwrot odwołania o wartości null.
  • CS8604 - Możliwy argument odwołania o wartości null dla parametru.
  • CS8605 - Rozpakowywanie możliwie pustej wartości.
  • CS8607 - Możliwe wartości null mogą nie być używane dla typu oznaczonego znakiem [NotNull] lub[DisallowNull]
  • CS8608 - Nullowalność typów referencyjnych w definicji typu nie pasuje do przesłoniętego członka.
  • CS8609 - Nullowalność typów odwołań w typie zwrotnym nie pasuje do zastępowanego członka.
  • CS8610 - Nullowalność typów referencyjnych w parametrze typu nie pasuje do nadpisanego elementu członkowskiego.
  • CS8611 - Nullowalność typów referencyjnych w parametrze typu nie odpowiada częściowej deklaracji metody.
  • CS8612 - Nullowalność typów referencyjnych nie zgadza się z niejawnie zaimplementowanym członkiem.
  • CS8613 - Nullowalność typów referencyjnych w typie zwrotnym nie jest zgodna z niejawnie zaimplementowanym członkiem.
  • CS8614 - Nullowalność typów referencyjnych parametru nie zgadza się z niejawnie zaimplementowanym członkiem.
  • CS8615 - Zero-wartościowość typów referencyjnych w typie nie zgadza się z zaimplementowanym członem.
  • CS8616 - Nullowalność typów referencyjnych w typie zwrotnym nie pasuje do zaimplementowanego członka.
  • CS8617 - Typ referencyjny o wartości null w typie parametru nie zgadza się z zaimplementowanym elementem członkowskim.
  • CS8618 - Zmienna niepusta musi zawierać wartość inną niż null przy opuszczaniu konstruktora. Rozważ zadeklarowanie jej jako dopuszczającej wartość null.
  • CS8619 - Nullowalność typów odwołań dla wartości nie jest zgodna z typem docelowym.
  • CS8620 - Argument nie może być użyty dla parametru z powodu różnic w możliwości przyjmowania wartości null przez typy odwołań.
  • CS8621 - Nullowalność typów referencyjnych w typie zwracanym nie pasuje do delegata docelowego (prawdopodobnie z powodu atrybutów dopuszczalności wartości null).
  • CS8622 - Nullability typów odwołań w typie parametru nie pasuje do delegata docelowego (prawdopodobnie z powodu atrybutów dopuszczania wartości null).
  • CS8623 - jawne stosowanie System.Runtime.CompilerServices.NullableAttribute jest niedozwolone.
  • CS8624 - Argument nie może być użyty jako dane wyjściowe z powodu różnic w niezerowości typów referencyjnych.
  • CS8625 - Nie można przekonwertować literału null na typ odwołania, który nie akceptuje wartości null.
  • CS8628 - Nie można użyć typu odwołania dopuszczającego wartość null podczas tworzenia obiektu.
  • CS8629 - Typ wartości dopuszczającej wartość null może być pusty.
  • CS8631 - Typ nie może być używany jako parametr typu w typie ogólnym lub metodzie. Wartość null argumentu typu nie jest zgodna z typem ograniczenia.
  • CS8632 - Adnotacja dla nullowalnych typów odwołań powinna być używana tylko w kodzie w kontekście adnotacji #nullable.
  • CS8633 - Nullability w ograniczeniach dla parametru typu metody nie zgadza się z ograniczeniami dla parametru typu metody interfejsu. Rozważ użycie jawnej implementacji interfejsu.
  • CS8634 - Typ nie może być używany jako parametr typu w typie ogólnym lub metodzie. Wartość null argumentu typu nie jest zgodna z ograniczeniem "class".
  • CS8636 - Nieprawidłowa opcja dla /nullable; musi być disable, enable, warnings lub annotations
  • CS8637 - oczekiwane enable, disablelub restore
  • CS8639 - Operator typeof nie może być używany na typie odwołania dopuszczającym wartość null
  • CS8643 - Nullowalność typów referencyjnych w specyfikatorze jawnego interfejsu nie pasuje do interfejsu implementowanego przez typ.
  • Typ CS8644 - nie implementuje elementu członkowskiego interfejsu. Wartość null typów odwołań w interfejsie implementowanych przez typ podstawowy nie jest zgodna.
  • CS8645 - Członek jest już wymieniony na liście interfejsów typu z inną nullowalnością typów referencyjnych.
  • CS8655 - Wyrażenie przełącznika nie obsługuje niektórych danych wejściowych o wartości null (nie jest wyczerpujące).
  • CS8667Deklaracje metody częściowej mają niespójną nullowalność w ograniczeniach dotyczących parametru typu.
  • CS8670 - Inicjator obiektów lub kolekcji niejawnie wyłuskuje członka, który może mieć wartość null.
  • CS8714 - Typ nie może być stosowany jako parametr typu w typie ogólnym lub metodzie. Zerowalność argumentu typu nie jest zgodna z ograniczeniem 'notnull'.
  • Parametr CS8762 - musi mieć wartość nienullową podczas opuszczania.
  • CS8763 - Metoda oznaczona [DoesNotReturn] nie powinna zwracać.
  • CS8764 - Nietypowość null typu zwracanego nie pasuje do elementu członkowskiego, który został zastąpiony (może wynikać z użycia atrybutów związanych z null).
  • CS8765 - Nullability typu parametru nie zgadza się z zastępowanym elementem członkowskim (prawdopodobnie z powodu atrybutów nullowalności).
  • CS8766 - Dopuszczalność wartości null typów referencyjnych w typie zwracanym nie zgadza się z niejawnie zaimplementowanym członkiem (prawdopodobnie ze względu na atrybuty dopuszczalności wartości null).
  • CS8767 - Nullowalność typów referencyjnych w typie parametru nie pasuje do niejawnie zaimplementowanego członka (prawdopodobnie z powodu atrybutów nullowalności).
  • CS8768 - Nijakość typów referencyjnych w typie wynikowym nie pasuje do zaimplementowanego członka (prawdopodobnie ze względu na atrybuty nijakości).
  • CS8769 - Nullowalność typów referencyjnych w typie parametru nie zgadza się z zaimplementowanym członkiem (prawdopodobnie z powodu atrybutów dotyczących nullowalności).
  • CS8770 - Metoda nie ma adnotacji [DoesNotReturn], aby pasować do zaimplementowanego lub nadpisanego członka.
  • Członek CS8774 - musi mieć wartość inną niż null przy wychodzeniu.
  • Element członkowski nie może być użyty w tym atrybucie.CS8776.
  • CS8775 - Element musi mieć wartość różną od null podczas zakończenia.
  • Parametr CS8777 - musi mieć wartość inną niż null podczas zamykania.
  • CS8819 - Nullowalność typów referencyjnych w typie zwrotnym nie odpowiada częściowej deklaracji metody.
  • Parametr CS8824 - musi mieć wartość inną niż null podczas zamykania, ponieważ parametr ma wartość inną niż null.
  • CS8825 - Wartość zwracana musi być inną niż null, ponieważ parametr ma wartość inną niż null.
  • CS8847 - Wyrażenie przełącznika nie obsługuje niektórych danych wejściowych o wartości null (nie jest wyczerpujące). Jednak wzorzec z klauzulą "when" może pomyślnie dopasować tę wartość.

Notatka

Analiza statyczna nie zawsze może wyłudić, w jakiej kolejności w określonym scenariuszu uzyskuje się dostęp do metod i czy metoda kończy się pomyślnie bez zgłaszania wyjątku. Te znane pułapki są dobrze opisane w sekcji "Znane pułapki".

Prawie wszystkie ostrzeżenia są rozwiązywane przy użyciu jednej z pięciu technik:

  • Konfigurowanie kontekstu dopuszczającego wartość null.
  • Dodawanie niezbędnych kontroli wartości null.
  • Dodawanie lub usuwanie adnotacji nullable ? lub !.
  • Dodawanie atrybutów opisujących semantykę o wartości null.
  • Prawidłowe inicjowanie zmiennych.

Jeśli dopiero zaczynasz używać typów referencyjnych dopuszczających wartość null, omówienie typów referencyjnych dopuszczających wartość null zawiera tło dotyczące problematyki tych typów oraz tego, jak działają, aby zapewniać ostrzeżenia o możliwych błędach w kodzie. Możesz również sprawdzić wskazówki dotyczące migracji do typów odwołań dopuszczających wartość null, aby dowiedzieć się więcej na temat włączania typów odwołań dopuszczających wartość null w istniejącym projekcie.

Konfigurowanie kontekstu dopuszczanego do wartości null

Następujące ostrzeżenia wskazują, że kontekst dopuszczający wartość null nie został poprawnie ustawiony:

  • CS8632 - Adnotacja dla typów odwołań dopuszczających wartości null powinna być używana tylko w kodzie w kontekście adnotacji #nullable.
  • CS8636 - Nieprawidłowa opcja dla /nullable; musi być disable, enable, warnings lub annotations
  • CS8637 - oczekiwano enable, disablelub restore

Nieprawidłowa składnia adnotacji

Te błędy i ostrzeżenia wskazują, że użycie adnotacji ! lub ? jest nieprawidłowe.

  • CS8598 - Operator tłumienia nie jest dozwolony w tym kontekście
  • CS8623 - jawne stosowanie System.Runtime.CompilerServices.NullableAttribute jest niedozwolone.
  • CS8628 - Nie można używać typu odwołania dopuszczalnego jako null podczas tworzenia obiektu.
  • CS8639 - Operator typeof nie może być używany na typie odwołania dopuszczającym wartość null

Adnotacja ? w deklaracji wskazuje, że zmienna może mieć wartość null. Nie wskazuje innego typu środowiska uruchomieniowego. Obie następujące deklaracje są tego samego typu środowiska uruchomieniowego:

string s1 = "a string";
string? s2 = "another string";

? to wskazówka dla kompilatora w sprawie oczekiwań dotyczących wartości null.

Adnotacja ! w wyrażeniu wskazuje, że wiesz, że wyrażenie jest bezpieczne i należy przyjąć, że nie ma wartości null.

  • Należy użyć tych adnotacji, a nie System.Runtime.CompilerServices.NullableAttribute w kodzie.
  • Ponieważ ? jest adnotacją, a nie typem, nie można jej używać z wyrażeniami typeoflub new.
  • Nie można zastosować operatora ! do wyrażenia zmiennej ani grupy metod.
  • Nie można zastosować operatora ! z lewej strony operatora dostępu członka, takiego jak obj.Field!.Method().

Możliwe odwołanie do wartości null

Ten zestaw ostrzeżeń ostrzega, że wyłuszczasz zmienną, której stan null jest być może null. Te ostrzeżenia są następujące:

  • CS8602 - Derefencja możliwego pustego odniesienia.
  • CS8670 - Inicjator obiektów lub kolekcji niejawnie wyłuskuje członek, który może mieć wartość null.

Poniższy kod przedstawia jeden przykład każdego z powyższych ostrzeżeń:

class Container
{
    public List<string>? States { get; set; }
}

internal void PossibleDereferenceNullExamples(string? message)
{
    Console.WriteLine(message.Length); // CS8602

    var c = new Container { States = { "Red", "Yellow", "Green" } }; // CS8670
}

W poprzednim przykładzie ostrzeżenie jest spowodowane tym, że Container, c, może mieć wartość null dla właściwości States. Przypisywanie nowych stanów do kolekcji, która może mieć wartość null, powoduje ostrzeżenie.

Aby usunąć te ostrzeżenia, należy dodać kod, aby zmienić stan tej zmiennej z null na not-null przed jej wyłuszczeniem. Ostrzeżenie inicjatora kolekcji może być trudniejsze do wykrycia. Kompilator wykrywa, że kolekcja może mieć wartość null , gdy inicjator dodaje do niej elementy.

W wielu przypadkach możesz rozwiązać te ostrzeżenia, sprawdzając, czy zmienna nie ma wartości null przed jej wyłuszczeniem. Rozważmy następujący przykład, który dodaje sprawdzanie wartości null przed wyłuszczeniem parametru message:

void WriteMessageLength(string? message)
{
    if (message is not null)
    {
        Console.WriteLine(message.Length);
    }
    
}

Poniższy przykład inicjuje pamięć dla elementu States i usuwa akcesor set. Użytkownicy klasy mogą modyfikować zawartość kolekcji, a pamięć dla kolekcji nigdy nie jest null.

class Container
{
    public List<string> States { get; } = new();
}

Inne przypadki otrzymania tych ostrzeżeń mogą być fałszywymi alarmami. Być może masz prywatną metodę narzędzia, która testuje wartość null. Kompilator nie wie, że metoda zapewnia sprawdzanie wartości null. Rozważmy następujący przykład, który korzysta z prywatnej metody pomocniczej: IsNotNull

public void WriteMessage(string? message)
{
    if (IsNotNull(message))
        Console.WriteLine(message.Length);
}

Kompilator ostrzega, że ​​podczas zapisywania właściwości message.Length możesz wyłuszczyć wartość null, ponieważ analiza statyczna wskazuje, że message może być null. Wiesz, że IsNotNull zapewnia sprawdzanie wartości null, a gdy zwraca true, stan dla message powinien być nie-null. Należy powiedzieć kompilatorowi te fakty. Jednym ze sposobów jest użycie operatora akceptującego wartość null, !. Możesz zmienić instrukcję WriteLine tak, aby odpowiadała następującemu kodowi.

Console.WriteLine(message!.Length);

Operator wybaczania wartości null sprawia, że wyrażenie jest nie-null, nawet jeśli było może-null bez zastosowania !. W tym przykładzie lepszym rozwiązaniem jest dodanie atrybutu do podpisu elementu IsNotNull:

private static bool IsNotNull([NotNullWhen(true)] object? obj) => obj != null;

Polecenie System.Diagnostics.CodeAnalysis.NotNullWhenAttribute informuje kompilator, że argument używany dla parametru obj nie ma wartości null , gdy metoda zwraca wartość true. Gdy metoda zwraca falsewartość , argument ma taki sam stan null, jaki miał przed wywołaną metodą.

Napiwek

Istnieje bogaty zestaw atrybutów, których można użyć do opisania sposobu, w jaki metody i właściwości wpływają na stan null. Można się o nich dowiedzieć z artykułu referencyjnego na temat atrybutów analizy statycznej dopuszczających wartości null.

Naprawienie ostrzeżenia dotyczącego dereferencjonowania zmiennej może mieć wartość null polega na jednej z trzech technik:

  • Dodaj brakujące sprawdzenie 'null'.
  • Dodaj atrybuty analizy zerowej w interfejsach API, aby wpłynąć na statyczną analizę stanu null kompilatora. Te atrybuty informują kompilator, kiedy zwracana wartość lub argument powinien być możliwie null lub nie null po wywołaniu metody.
  • Zastosuj operator łagodzący null ! do wyrażenia, które wymusza, aby stan był niepusty.

Możliwe przypisanie wartości null do odwołania niemożliwego do użycia

Ten zbiór ostrzeżeń informuje, że przypisujesz zmienną, której typ nie dopuszcza wartości null, do wyrażenia, którego stan null to może mieć wartość null. Te ostrzeżenia są następujące:

  • CS8597 - Wartość zgłaszana może mieć wartość null.
  • CS8600 - Konwertowanie literału null lub możliwej wartości null na typ nie-nullowalny.
  • CS8601 - Możliwe przypisanie odwołania o wartości null.
  • CS8603 - Możliwe zwracanie referencji zerowej.
  • CS8604 - Możliwy argument odwołania o wartości null dla parametru.
  • CS8605 - Rozpakowywanie wartości, która prawdopodobnie jest nullem.
  • CS8625 - Nie można przekonwertować literału null na typ odwołania bez wartości null.
  • Możliwy typ wartości zerowej CS8629 - może mieć wartość null.

Kompilator emituje te ostrzeżenia podczas próby przypisania wyrażenia, które może być null do zmiennej niemającej wartości null. Na przykład:

string? TryGetMessage(int id) => "";

string msg = TryGetMessage(42);  // Possible null assignment.

Różne ostrzeżenia wskazują szczegółowe informacje o kodzie, takie jak przypisanie, rozpakowywanie przypisania, instrukcje zwracane, argumenty metod i zgłaszanie wyrażeń.

Aby rozwiązać te ostrzeżenia, możesz wykonać jedną z trzech akcji. Jednym ze sposobów jest dodanie adnotacji ?, aby uczynić zmienną typem odwołania dopuszczającym wartość null. Ta zmiana może spowodować inne ostrzeżenia. Zmiana zmiennej z odwołania nienullowego na odwołanie nullable zmienia jej domyślny stan null z not-null na może-null. Analiza statyczna kompilatora znajduje wystąpienia, w których należy wyłuskać zmienną, która jest być może ma wartość null.

Inne akcje informują kompilator, że po prawej stronie przypisania wartość nie jest null. Wyrażenie po prawej stronie może być zaznaczone wartością null przed przypisaniem, jak pokazano w poniższym przykładzie:

string notNullMsg = TryGetMessage(42) ?? "Unknown message id: 42";

W poprzednich przykładach pokazano przypisanie wartości zwracanej metody. Dodaj adnotację do metody (lub właściwości), aby wskazać, kiedy metoda zwraca wartość inną niż null. Często System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute określa, że wartość zwracana nie ma wartości null , gdy argument wejściowy nie ma wartości null. Inną alternatywą jest dodanie operatora ignorującego null ! po prawej stronie:

string msg = TryGetMessage(42)!;

Naprawienie ostrzeżenia dotyczącego przypisywania wyrażenia może o wartości null do zmiennej not-null obejmuje jedną z czterech technik:

  • Zmień lewą stronę przypisania na typ akceptujący wartość null. Ta akcja może wprowadzać nowe ostrzeżenia podczas dereferencowania tej zmiennej.
  • Upewnij się, że przed przypisaniem zostało wykonane sprawdzenie wartości null.
  • Dodaj adnotację do interfejsu API, który tworzy prawą stronę przypisania.
  • Dodaj operator wybaczający null do prawej strony przypisania.

Niezaimulowalne odwołanie nie jest inicjowane

Ten zestaw ostrzeżeń informuje, że przypisujesz wartość zmiennej o typie niepustym do wyrażenia, którego stan null to może-null. Te ostrzeżenia są następujące:

  • CS8618 - Zmienna niepusta musi zawierać wartość inną niż null podczas zamykania konstruktora. Rozważ zadeklarowanie go jako dopuszczającego wartość null.
  • Parametr CS8762 - musi mieć wartość inną niż null przy wychodzeniu.

Rozważmy następującą klasę jako przykład:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Ani FirstName, ani LastName nie są gwarantowane do zainicjowania. Jeśli ten kod jest nowy, rozważ zmianę interfejsu publicznego. Powyższy przykład można zaktualizować w następujący sposób:

public class Person
{
    public Person(string first, string last)
    {
        FirstName = first;
        LastName = last;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Jeśli musisz utworzyć Person obiekt przed ustawieniem nazwy, możesz zainicjować właściwości przy użyciu domyślnej wartości innej niż null:

public class Person
{
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
}

Inną alternatywą jest zmiana tych elementów członkowskich na referencyjne typy dopuszczające wartość null. Klasa może być zdefiniowana Person w następujący sposób, jeśli null powinna być dozwolona dla nazwy:

public class Person
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
}

Istniejący kod czasami wymaga innych zmian, aby poinformować kompilator o semantyce wartości null dla tych członków. Może mieć wiele konstruktorów, a klasa ma prywatną metodę pomocnika, która inicjuje co najmniej jeden element członkowczy. Kod inicjowania można przenieść do jednego konstruktora i upewnić się, że wszystkie konstruktory wywołają ten z typowym kodem inicjowania. Możesz też użyć atrybutów System.Diagnostics.CodeAnalysis.MemberNotNullAttribute i System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute. Te atrybuty informują kompilator, że element członkowski jest nie null po powrocie metody. 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 adnotacjami 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";
    }
}

Na koniec możesz użyć operatora ignorującego null, aby wskazać, że członek jest inicjalizowany gdzie indziej w kodzie. W innym przykładzie rozważmy następujące klasy reprezentujące model Entity Framework Core:

public class TodoItem
{
    public long Id { get; set; }
    public string? Name { get; set; }
    public bool IsComplete { get; set; }
}

public class TodoContext : DbContext
{
    public TodoContext(DbContextOptions<TodoContext> options)
        : base(options)
    {
    }

    public DbSet<TodoItem> TodoItems { get; set; } = null!;
}

Właściwość DbSet jest inicjowana na null!. Informuje to kompilator, że właściwość jest ustawiona na wartość not-null . W rzeczywistości baza DbContext wykonuje inicjowanie zestawu. Analiza statyczna kompilatora nie wykrywa tego. Aby uzyskać więcej informacji na temat pracy z typami referencyjnymi dopuszczanymi wartościami null i programem Entity Framework Core, zobacz artykuł Praca z typami referencyjnymi dopuszczanymi wartościami null w programie EF Core.

Naprawienie ostrzeżenia dotyczącego braku inicjowania niepodlegającego do wartości członka obejmuje jedną z czterech technik:

  • Zmień konstruktory lub inicjatory pól, aby upewnić się, że wszystkie składniki niemające wartości null są zainicjowane.
  • Zmień jeden lub więcej członków na typ dopuszczający wartość null.
  • Dodaj adnotacje do metod pomocnika, aby wskazać, którzy członkowie są przypisani.
  • Dodaj inicjalizator do null!, aby wskazać, że element członkowski został zainicjalizowany w innym kodzie.

Niezgodność deklaracji nullowalności

Wiele ostrzeżeń wskazuje niezgodność wartości null między sygnaturami metod, delegatów lub parametrów typu.

  • CS8608 - Nullelość typów referencyjnych w typie nie pasuje do przesłoniętego elementu.
  • CS8609 - Nullowalność typów referencyjnych w typie zwrotnym nie odpowiada zastępowanemu elementowi.
  • CS8610 - Nullowalność typów referencyjnych w parametrze typu nie odpowiada zastępowanemu elementowi członkowskiemu.
  • CS8611 - Typ odwołania w parametrze typu ma różną anulowalność niż w deklaracji częściowej metody.
  • CS8612 - Nullability typów odwołań w typach nie pasuje do niejawnie zaimplementowanego elementu.
  • CS8613 - Nullowalność typów referencyjnych w typie zwracanym jest niezgodna z niejawnie zaimplementowanym członkiem.
  • CS8614 - Nullability typów odwołań w typie parametru nie odpowiada niejawnie zaimplementowanemu członkowi.
  • CS8615 - Nullowalność typów referencyjnych w typie nie zgadza się z zaimplementowanym elementem członkowskim.
  • CS8616 - Nieprawidłowa nullowalność typów referencyjnych w typie zwrotnym nie zgadza się z typem w zaimplementowanym członku.
  • CS8617 - Nullowalność typów referencyjnych w typie parametru nie jest zgodna z zaimplementowanym członem.
  • CS8619 - Nullowalność typów referencyjnych nie jest zgodna z typem docelowym.
  • CS8620 - Argument nie może być użyty dla parametru ze względu na różnice w możliwościach przypisania wartości null typów referencyjnych.
  • CS8621 - Nullowość typów referencyjnych w typie zwracanym nie pasuje do delegata docelowego (prawdopodobnie z powodu atrybutów związaną z dopuszczalnością wartości null).
  • CS8622 - Nullowalność typów odwołań w parametrze nie pasuje do delegata docelowego (prawdopodobnie z powodu atrybutów nullowalności).
  • CS8624 - Nie można używać argumentu jako wyniku ze względu na różnice w nullowalności typów referencyjnych.
  • CS8631 - Typ nie może być używany jako parametr typu w typie ogólnym lub metodzie. Wartość null argumentu typu nie jest zgodna z typem ograniczenia.
  • CS8633 - Nullability w ograniczeniach dla parametru typu metody nie pasuje do ograniczeń dla parametru typu metody interfejsu. Rozważ użycie jawnej implementacji interfejsu.
  • CS8634 - Typ nie może być używany jako parametr typu w typie ogólnym lub metodzie. Wartość null argumentu typu nie jest zgodna z ograniczeniem "class".
  • CS8643 - Nullowalność typów referencyjnych w specyfikatorze jawnego interfejsu nie pasuje do interfejsu zaimplementowanego przez dany typ.
  • Typ CS8644 - nie implementuje elementu członkowskiego interfejsu. Wartość null typów odwołań w interfejsie implementowanych przez typ podstawowy nie jest zgodna.
  • Element CS8645 - jest już wymieniony na liście interfejsów na typie z różnymi wartościami null typów referencyjnych.
  • Deklaracja częściowej metody CS8667 - ma niespójną nullowalność w ograniczeniach dla parametru typu.
  • CS8714 - Typ nie może być używany jako parametr typu w typie ogólnym lub metodzie. Nulowalność argumentu typu nie jest zgodna z 'notnull' ograniczeniem.
  • CS8764 - Nullability typu zwracanego nie pasuje do zastępowanego elementu członkowskiego (prawdopodobnie z powodu atrybutów dopuszczalności null).
  • CS8765 - Nullość typu parametru nie pasuje do zastępowanego elementu członkowskiego (prawdopodobnie z powodu atrybutów nullowalności).
  • CS8766 - Umiejscowienie dopuszczenia NULL w typach referencyjnych w typie zwracanym nie pasuje do członka zaimplementowanego niejawnie (prawdopodobnie z powodu atrybutów dopuszczenia null).
  • CS8767 - Nullowalność typów referencyjnych w typie parametru nie zgadza się z niejawnie zaimplementowanym członem (prawdopodobnie z powodu atrybutów nullowalności).
  • CS8768 - Nullability typów referencyjnych w typie zwrotnym nie pasuje do wdrożonego elementu członkowskiego (prawdopodobnie ze względu na atrybuty dotyczące dopuszczalności wartości null).
  • CS8769 - Nullowalność typów referencyjnych w parametrach nie pasuje do zaimplementowanego członka (prawdopodobnie z powodu atrybutów nullowalności).
  • CS8819 - Nullowalność typów referencyjnych w typie zwrotnym nie odpowiada częściowej deklaracji metody.

Poniższy kod demonstruje CS8764:

public class B
{
    public virtual string GetMessage(string id) => string.Empty;
}
public class D : B
{
    public override string? GetMessage(string? id) => default;
}

W poprzednim przykładzie przedstawiono metodę virtual w klasie bazowej i override z inną nullowalnością. Klasa bazowa zwraca ciąg niezwracający wartości null, ale klasa pochodna zwraca ciąg mogący zwracać wartość null. Jeśli string i string? są zamienione, jest to dozwolone, ponieważ klasa pochodna jest bardziej restrykcyjna. Podobnie deklaracje parametrów powinny być zgodne. Parametry w metodzie przesłoniętej mogą zezwalać na wartość null, nawet gdy klasa bazowa tego nie robi.

Inne sytuacje mogą generować te ostrzeżenia. W deklaracji metody interfejsu i implementacji tej metody istnieje niezgodność. Lub typ delegata i wyrażenie dla tego delegata różnią się. Parametr typu i argument typu różnią się pod względem możliwości przyjmowania wartości null.

Aby naprawić te ostrzeżenia, zaktualizuj odpowiednią deklarację.

Kod nie jest zgodny z deklaracją atrybutu

W poprzednich sekcjach omówiono sposób używania atrybutów do analizy statycznej dopuszczającej wartość null w celu informowania kompilatora o semantyce null kodu. Kompilator ostrzega, jeśli kod nie jest zgodny z obietnicami tego atrybutu:

  • CS8607 - Możliwe wartości null mogą nie być używane dla typu oznaczonego znakiem [NotNull] lub[DisallowNull]
  • CS8763 - Metoda oznaczona [DoesNotReturn] nie powinna zwracać.
  • CS8770 - Metoda nie ma [DoesNotReturn] adnotacji, aby dopasować zaimplementowany lub zastąpiony element członkowski.
  • Członek CS8774 - musi mieć wartość inną niż null podczas zakończenia.
  • CS8775 - Member musi mieć wartość inną niż null podczas wychodzenia.
  • CS8776 - Członek nie może być używany w tym atrybucie.
  • Parametr CS8777 - musi mieć wartość inną niż null podczas wychodzenia.
  • CS8824 - Parametr musi mieć wartość niebędącą nullem podczas wychodzenia, ponieważ parametr nie może być nullem.
  • CS8825 - Wartość zwracana musi być niepusta, ponieważ parametr jest inny niż null.

Rozważmy następującą metodę:

public bool TryGetMessage(int id, [NotNullWhen(true)] out string? message)
{
    message = null;
    return true;

}

Kompilator generuje ostrzeżenie, ponieważ do parametru message przypisano nulli metoda zwraca true. Atrybut NotNullWhen wskazuje, że nie powinno się to zdarzyć.

Aby rozwiązać te ostrzeżenia, zaktualizuj kod, aby był zgodny z oczekiwaniami zastosowanych atrybutów. Można zmienić atrybuty lub algorytm.

Wyczerpujące wyrażenie przełącznika

Wyrażenia przełącznika muszą być wyczerpujące, co oznacza, że wszystkie wartości wejściowe muszą być obsługiwane. Nawet w przypadku typów odwołań bez wartości null wartość null musi być uwzględniona. Kompilator zgłasza ostrzeżenia, gdy wartość null nie jest obsługiwana:

  • CS8655 - Wyrażenie przełącznika nie obsługuje niektórych danych wejściowych o wartości null (nie jest wyczerpujące).
  • CS8847 - Wyrażenie przełącznika nie obsługuje niektórych danych wejściowych o wartości null (nie jest wyczerpujące). Jednak wzorzec z klauzulą "when" może pomyślnie dopasować tę wartość.

Poniższy przykładowy kod demonstruje ten warunek:

int AsScale(string status) =>
    status switch
    {
        "Red" => 0,
        "Yellow" => 5,
        "Green" => 10,
        { } => -1
    };

Wyrażenie wejściowe to string, a nie string?. Kompilator nadal generuje to ostrzeżenie. Wzorzec { } obsługuje wszystkie wartości inne niż null, ale nie jest zgodny z nullparametrem . Aby rozwiązać te błędy, możesz dodać jawny przypadek null lub zastąpić { } wzorcem _ (odrzuć). Wzorzec odrzucenia pasuje do wartości null, a także do każdej innej wartości.