Rozwiązywanie problemów z ostrzeżeniami dopuszczanymi do wartości null

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

  • CS8597 - Wartość zgłaszana może mieć wartość null.
  • CS8600 - Konwertowanie literału null lub możliwej wartości null na typ niepusty.
  • CS8601 - Możliwe przypisanie odwołania o 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 - Rozpałkanie prawdopodobnie wartości null.
  • CS8607 - Możliwe wartości null mogą nie być używane dla typu oznaczonego znakiem [NotNull] lub[DisallowNull]
  • CS8608 - Nullability typów odwołań w typie nie pasuje do przesłoniętego elementu członkowskiego.
  • CS8609 - Nullability typów odwołań w typie zwrotnym nie pasuje do zastępowanego elementu członkowskiego.
  • CS8610 - Nullability typów odwołań w parametrze typu nie pasuje do zastępowanego elementu członkowskiego.
  • CS8611 - Nullability typów odwołań w parametrze typu nie jest zgodna z częściową deklaracją metody.
  • CS8612 - Nullability typów odwołań w typie nie pasuje do niejawnie zaimplementowanego elementu członkowskiego.
  • CS8613 - Nullability typów odwołań w typie zwrotnym nie pasuje do niejawnie zaimplementowanego elementu członkowskiego.
  • CS8614 - Nullability typów odwołań w typie parametru nie pasuje do niejawnie zaimplementowanego elementu członkowskiego.
  • CS8615 - Nullability typów odwołań w typie nie pasuje do zaimplementowanego elementu członkowskiego.
  • CS8616 - Nullability typów odwołań w typie zwrotnym nie pasuje do zaimplementowanego elementu członkowskiego.
  • CS8617 - Nullability typów odwołań w typie parametru nie pasuje do zaimplementowanego elementu członkowskiego.
  • CS8618 - Zmienna niepusta musi zawierać wartość inną niż null podczas zamykania konstruktora. Rozważ zadeklarowanie go jako dopuszczającego wartość null.
  • CS8619 - Nullability typów odwołań w wartości nie jest zgodna z typem docelowym.
  • Argument CS8620 - nie może być używany dla parametru ze względu na różnice w wartości null typów odwołań.
  • CS8621 - Nullability typów odwołań w zwracanych typach nie pasuje do delegata docelowego (prawdopodobnie z powodu atrybutów dopuszczalnoś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).
  • Argument CS8624 - nie może być używany jako dane wyjściowe ze względu na różnice w wartości null typów odwołań.
  • CS8625 - Nie można przekonwertować literału null na typ odwołania bez wartości null.
  • Typ wartości dopuszczanej do wartości CS8629 - może mieć wartość null.
  • 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 - Nullability typów odwołań w specyfikatorze jawnego interfejsu nie pasuje do interfejsu zaimplementowanego 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.
  • Element członkowski CS8645 - jest już wymieniony na liście interfejsów na liście typów o różnych wartościach null typów odwołań.
  • CS8655 - Wyrażenie przełącznika nie obsługuje niektórych danych wejściowych o wartości null (nie jest wyczerpujące).
  • Deklaracje metody częściowej CS8667 - mają niespójną wartość null w ograniczeniach dla parametru typu.
  • CS8670 - Inicjator obiektów lub kolekcji niejawnie wyłuskiwuje prawdopodobnie element członkowski o wartości null.
  • CS8714 - 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 "notnull".
  • Parametr CS8762 - musi mieć wartość inną niż null podczas zamykania.
  • CS8763 - Metoda oznaczona [DoesNotReturn] nie powinna zwracać.
  • CS8764 - Nullability typu zwracanego nie pasuje do zastępowanego elementu członkowskiego (prawdopodobnie z powodu atrybutów dopuszczalności null).
  • CS8765 - Nullability typu parametru nie pasuje do zastępowanego elementu członkowskiego (prawdopodobnie z powodu atrybutów dopuszczalności null).
  • CS8766 - Nullability typów odwołań w zwracaniu typu nie pasuje do niejawnie zaimplementowanego elementu członkowskiego (prawdopodobnie ze względu na atrybuty dopuszczalności null).
  • CS8767 - Nullability typów odwołań w typie parametru nie pasuje do niejawnie zaimplementowanego elementu członkowskiego (prawdopodobnie ze względu na atrybuty dopuszczalności null).
  • CS8768 - Nullability typów odwołań w typie zwrotnym nie pasuje do zaimplementowanego elementu członkowskiego (prawdopodobnie ze względu na atrybuty dopuszczalności null).
  • CS8769 - Nullability typów odwołań w typie parametru nie pasuje do zaimplementowanego elementu członkowskiego (prawdopodobnie z powodu atrybutów dopuszczalności null).
  • Metoda CS8770 - nie ma [DoesNotReturn] adnotacji, aby dopasować zaimplementowany lub zastąpiony element członkowski.
  • Element członkowski CS8774 - musi mieć wartość inną niż null podczas zamykania.
  • W tym atrybucie nie można użyć elementu członkowskiego CS8776 - .
  • Element członkowski CS8775 - musi mieć wartość inną niż null podczas zamykania.
  • Parametr CS8777 - musi mieć wartość inną niż null podczas zamykania.
  • CS8819 - Nullability typów odwołań w typie zwrotnym nie jest zgodna z częściową deklaracją metody.
  • Parametr CS8824 - musi mieć wartość inną niż null podczas zamykania, ponieważ parametr ma wartość inną niż null.
  • Wartość zwracana CS8825 - musi być niepusta, 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ść.

Celem ostrzeżeń dopuszczających wartość null jest zminimalizowanie prawdopodobieństwa, że aplikacja zgłasza System.NullReferenceException błąd po uruchomieniu. Aby osiągnąć ten cel, kompilator używa analizy statycznej i ostrzeżeń dotyczących problemów, gdy kod zawiera konstrukcje, które mogą prowadzić do wyjątków odwołania o wartości null. Kompilator udostępnia informacje dotyczące analizy statycznej, stosując adnotacje i atrybuty typu. Te adnotacje i atrybuty opisują wartość null argumentów, parametrów i elementów członkowskich typów. W tym artykule poznasz różne techniki rozwiązywania problemów z ostrzeżeniami dopuszczanymi do 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 dopuszczanymi wartości null i rdzeniem platformy Entity Framework, w temacie Praca z typami referencyjnymi dopuszczanymi do wartości null.

Zajmiesz się prawie wszystkimi ostrzeżeniami przy użyciu jednej z czterech technik:

  • Dodawanie niezbędnych kontroli wartości null.
  • Dodawanie ? lub ! dopuszczanie wartości null adnotacji.
  • Dodawanie atrybutów opisujących semantykę o wartości null.
  • Prawidłowe inicjowanie zmiennych.

Możliwe wyłusczenie 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 - Dereference możliwego odwołania o wartości null.
  • CS8670 - Inicjator obiektów lub kolekcji niejawnie wyłuskiwuje prawdopodobnie element członkowski o wartości 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 powyższym przykładzie ostrzeżenie jest spowodowane tym, że Containerwłaściwość , cmoże mieć wartość States null. 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 null tej zmiennej na wartość not-null przed wyłuszczeniem go. 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żna naprawić te ostrzeżenia, sprawdzając, czy zmienna nie ma wartości null przed jej wyłuszczeniem. Przed wyłuszczeniem parametru message należy rozważyć następujące kwestie, które dodają sprawdzanie wartości null:

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

Poniższy przykład inicjuje magazyn pomocniczy dla elementu States i usuwa metodę set dostępu. Konsumenci klasy mogą modyfikować zawartość kolekcji, a magazyn kolekcji nigdy nie nulljest :

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

Inne wystąpienia w przypadku otrzymania tych ostrzeżeń mogą być fałszywie dodatnie. 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 narzędzia: 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że zostać wyłuszczenie wartości null, ponieważ jego analiza statyczna określa, że message może to być nullwartość . Być może wiesz, że IsNotNull zapewnia sprawdzanie wartości null, a gdy zwraca truewartość , stan message null nie powinien mieć wartości null. Należy powiedzieć kompilatorowi te fakty. Jednym ze sposobów jest użycie operatora forgiving o wartości null, !. Możesz zmienić instrukcję tak WriteLine , aby odpowiadała następującemu kodowi:

Console.WriteLine(message!.Length);

Operator forgiving o wartości null sprawia, że wyrażenie nie ma wartości null , nawet jeśli wartość może mieć wartość 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. Informacje na temat nich można znaleźć w artykule dotyczącym atrybutów analizy statycznej dopuszczanej do wartości null.

Naprawienie ostrzeżenia dotyczącego wyłudlenia zmiennej może o wartości null obejmuje jedną z trzech technik:

  • Dodaj brak sprawdzania wartości null.
  • Dodaj atrybuty analizy null w interfejsach API, aby wpłynąć na statyczną analizę stanu null kompilatora. Te atrybuty informują kompilator, gdy zwracana wartość lub argument powinien mieć wartość null lub wartość not-null po wywołaniu metody.
  • Zastosuj operator ! forgiving o wartości null do wyrażenia, aby wymusić, że stan nie ma wartości null.

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

Ten zestaw ostrzeżeń ostrzega, że przypisujesz zmienną, której typ jest niemożliwy do pisania do wyrażenia, którego stan null ma wartość 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 niepusty.
  • CS8601 - Możliwe przypisanie 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 - Rozpałkanie prawdopodobnie wartości null.
  • CS8625 - Nie można przekonwertować literału null na typ odwołania bez wartości null.
  • Typ wartości dopuszczanej do wartości CS8629 - może mieć wartość null.

Kompilator emituje te ostrzeżenia podczas próby przypisania wyrażenia, które może mieć wartość null do zmiennej, która jest niemożliwa do dodania. 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 z nich jest dodanie adnotacji ? w celu utworzenia zmiennej typu odwołania dopuszczanego do wartości null. Ta zmiana może spowodować inne ostrzeżenia. Zmiana zmiennej z odwołania innego niż null do odwołania dopuszczanego do wartości null zmienia domyślny stan null z not-null na być może-null. Analiza statyczna kompilatora może znajdować wystąpienia, w których wyłuszczasz zmienną, która może mieć wartość null.

Inne akcje instruują kompilatorowi, że po prawej stronie przypisania nie ma wartości 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. Możesz dodać 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 forgiving o wartości null do ! prawej strony:

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 dopuszczalny do wartości null. Ta akcja może spowodować wprowadzenie nowych ostrzeżeń w przypadku wyłudzenia tej zmiennej.
  • Przed przypisaniem podaj sprawdzanie wartości null.
  • Dodaj adnotację do interfejsu API, który tworzy prawą stronę przypisania.
  • Dodaj operator forgiving o wartości null do prawej strony przypisania.

Niezaimulowalne odwołanie nie jest inicjowane

Ten zestaw ostrzeżeń ostrzega, że przypisujesz zmienną, której typ jest niepusty do wyrażenia, którego stan null ma wartość może mieć wartość 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 podczas zamykania.

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

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

Ani nie FirstNameLastName są gwarantowane zainicjowane. 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;
}

Innym rozwiązaniem może być zmiana tych elementów członkowskich na typy odwołań dopuszczających 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 może wymagać innych zmian w celu poinformowania kompilatora o semantyce o wartości null dla tych elementów członkowskich. Być może utworzono wiele konstruktorów, a klasa może mieć 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ć System.Diagnostics.CodeAnalysis.MemberNotNullAttribute atrybutów i System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute . Te atrybuty informują kompilator, że element członkowski nie ma wartości null po wywołaniu 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 forgiving o wartości null, aby wskazać, że element członkowski jest inicjowany w innym 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 pobiera tej funkcji. 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 elementu członkowskiego nienależącego do wartości obejmuje jedną z czterech technik:

  • Zmień konstruktory lub inicjatory pól, aby upewnić się, że wszystkie nienullable składowe są inicjowane.
  • Zmień co najmniej jeden element członkowny na typy dopuszczane do wartości null.
  • Dodaj adnotacje do wszystkich metod pomocnika, aby wskazać, które elementy członkowskie są przypisane.
  • Dodaj inicjator, aby wskazać null! , że element członkowski został zainicjowany w innym kodzie.

Niezgodność deklaracji dopuszczalności null

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

  • CS8608 - Nullability typów odwołań w typie nie pasuje do przesłoniętego elementu członkowskiego.
  • CS8609 - Nullability typów odwołań w typie zwrotnym nie pasuje do zastępowanego elementu członkowskiego.
  • CS8610 - Nullability typów odwołań w parametrze typu nie pasuje do zastępowanego elementu członkowskiego.
  • CS8611 - Nullability typów odwołań w parametrze typu nie jest zgodna z częściową deklaracją metody.
  • CS8612 - Nullability typów odwołań w typie nie pasuje do niejawnie zaimplementowanego elementu członkowskiego.
  • CS8613 - Nullability typów odwołań w typie zwrotnym nie pasuje do niejawnie zaimplementowanego elementu członkowskiego.
  • CS8614 - Nullability typów odwołań w typie parametru nie pasuje do niejawnie zaimplementowanego elementu członkowskiego.
  • CS8615 - Nullability typów odwołań w typie nie pasuje do zaimplementowanego elementu członkowskiego.
  • CS8616 - Nullability typów odwołań w typie zwrotnym nie pasuje do zaimplementowanego elementu członkowskiego.
  • CS8617 - Nullability typów odwołań w typie parametru nie pasuje do zaimplementowanego elementu członkowskiego.
  • CS8619 - Nullability typów odwołań w wartości nie jest zgodna z typem docelowym.
  • Argument CS8620 - nie może być używany dla parametru ze względu na różnice w wartości null typów odwołań.
  • CS8621 - Nullability typów odwołań w zwracanych typach nie pasuje do delegata docelowego (prawdopodobnie z powodu atrybutów dopuszczalnoś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).
  • Argument CS8624 - nie może być używany jako dane wyjściowe ze względu na różnice w wartości null typów odwołań.
  • 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 - Nullability typów odwołań w specyfikatorze jawnego interfejsu nie pasuje do interfejsu zaimplementowanego 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.
  • Element członkowski CS8645 - jest już wymieniony na liście interfejsów na liście typów o różnych wartościach null typów odwołań.
  • Deklaracje metody częściowej CS8667 - mają niespójną wartość null w ograniczeniach dla parametru typu.
  • CS8714 - 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 "notnull".
  • CS8764 - Nullability typu zwracanego nie pasuje do zastępowanego elementu członkowskiego (prawdopodobnie z powodu atrybutów dopuszczalności null).
  • CS8765 - Nullability typu parametru nie pasuje do zastępowanego elementu członkowskiego (prawdopodobnie z powodu atrybutów dopuszczalności null).
  • CS8766 - Nullability typów odwołań w zwracaniu typu nie pasuje do niejawnie zaimplementowanego elementu członkowskiego (prawdopodobnie ze względu na atrybuty dopuszczalności null).
  • CS8767 - Nullability typów odwołań w typie parametru nie pasuje do niejawnie zaimplementowanego elementu członkowskiego (prawdopodobnie ze względu na atrybuty dopuszczalności null).
  • CS8768 - Nullability typów odwołań w typie zwrotnym nie pasuje do zaimplementowanego elementu członkowskiego (prawdopodobnie ze względu na atrybuty dopuszczalności null).
  • CS8769 - Nullability typów odwołań w typie parametru nie pasuje do zaimplementowanego elementu członkowskiego (prawdopodobnie z powodu atrybutów dopuszczalności null).
  • CS8819 - Nullability typów odwołań w typie zwrotnym nie jest zgodna z częściową deklaracją 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ą wartością null. Klasa bazowa zwraca ciąg bez wartości null, ale klasa pochodna zwraca ciąg dopuszczalny do wartości null. string Jeśli i string? są odwrócone, byłoby dozwolone, ponieważ klasa pochodna jest bardziej restrykcyjna. Podobnie deklaracje parametrów powinny być zgodne. Parametry w metodzie przesłonięcia mogą zezwalać na wartość null nawet wtedy, gdy klasa bazowa nie.

Inne sytuacje mogą generować te ostrzeżenia. Może istnieć niezgodność w deklaracji metody interfejsu i implementacji tej metody. Lub typ delegata i wyrażenie dla tego delegata może się różnić. Parametr typu i argument typu mogą różnić się w przypadku 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życia 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ć.
  • Metoda CS8770 - nie ma [DoesNotReturn] adnotacji, aby dopasować zaimplementowany lub zastąpiony element członkowski.
  • Element członkowski CS8774 - musi mieć wartość inną niż null podczas zamykania.
  • Element członkowski CS8775 - musi mieć wartość inną niż null podczas zamykania.
  • W tym atrybucie nie można użyć elementu członkowskiego CS8776 - .
  • Parametr CS8777 - musi mieć wartość inną niż null podczas zamykania.
  • Parametr CS8824 - musi mieć wartość inną niż null podczas zamykania, ponieważ parametr ma wartość inną niż null.
  • Wartość zwracana CS8825 - musi być niepusta, ponieważ parametr ma wartość inną 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ż message parametr jest przypisany null, a metoda zwraca truewartość . 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żesz 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 należy null uwzględnić wartość. 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 string?nie . 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 null przypadek lub zastąpić { }_ wzorcem (odrzuć). Wzorzec odrzucania jest zgodny z wartością null, a także dowolną inną wartością.