Číst v angličtině

Sdílet prostřednictvím


Vyřešení výstrah o hodnotě null

Účelem výstrah o hodnotách null je minimalizovat pravděpodobnost, že vaše aplikace při spuštění vyvolá výjimku System.NullReferenceException. K dosažení tohoto cíle kompilátor používá statickou analýzu a zobrazí upozornění, pokud váš kód obsahuje konstrukty, které můžou vést k výjimkám nulového odkazu. Kompilátoru poskytnete informace pro jeho statickou analýzu použitím poznámek a atributů typu. Tyto poznámky a atributy popisují nulovost argumentů, parametrů a členů vašich typů. V tomto článku se naučíte různé techniky, jak řešit výstrahy o nullovatelnosti, které kompilátor generuje při statické analýze. Zde popsané techniky jsou určené pro obecný kód jazyka C#. Naučte se pracovat s odkazovými typy s možnou hodnotou null a jádrem Entity Framework při práci s odkazovými typy s možnou hodnotou null.

Odkazové typy s možnou hodnotou null, včetně operátorů ? a !, jsou povoleny pouze v případě, že je kontext s možnou hodnotou null nastaven na enable nebo annotations. Kontext s možnou hodnotou null můžete nastavit pomocí možnosti kompilátoru Nullable v souboru projektu nebo pomocí #nullable pragma ve zdrojovém kódu.

Tento článek se zabývá následujícími upozorněními kompilátoru:

  • CS8597 - Hodnota, která byla vyhozena, může být nulová.
  • CS8598 - Operátor potlačení není v tomto kontextu povolen
  • CS8600 - Převod hodnoty null nebo možné null hodnoty na typ, který nemůže mít hodnotu null.
  • CS8601 - Možné přiřazování nullového odkazu
  • CS8602 - Dereference možná nulového odkazu.
  • CS8603 - Možné vrácení nullového odkazu.
  • CS8604 - Možný argument odkazu null pro parametr.
  • CS8605 - Rozbalení hodnoty, která může být null.
  • CS8607 - Možnou hodnotu null nelze použít pro typ označený [NotNull] nebo[DisallowNull]
  • CS8608 - Nullability odkazových typů v typu neodpovídá přepsanému členu.
  • CS8609 - Nullovatelnost odkazových typů v návratovém typu neodpovídá přepsanému členu.
  • CS8610 - Nullovatelnost odkazových typů u parametru typu neodpovídá přepsanému členovi.
  • CS8611 - Nulovatelnost odkazových typů v parametru typu neodpovídá částečné deklaraci metody.
  • CS8612 - Nulenost odkazových typů v typu neodpovídá implicitně implementovanému členu.
  • CS8613 - Nullovatelnost odkazových typů v návratovém typu neodpovídá implicitně implementovanému členu.
  • CS8614: Nulovatelnost odkazových typů v typu parametru neodpovídá implicitně implementovanému členu.
  • CS8615 - Nullovatelnost odkazových typů v typu neodpovídá implementovanému členu.
  • CS8616 - Neznámost odkazových typů ve návratovém typu neodpovídá implementovanému členu.
  • CS8617 - Nullabilita odkazových typů v typu parametru neodpovídá implementovanému členu.
  • Cs8618 - Proměnná bez hodnoty null musí při ukončení konstruktoru obsahovat nenulovou hodnotu. Zvažte jeho deklarování jako nullable.
  • CS8619 - Nullabilita odkazových typů v rámci hodnoty neodpovídá cílovému typu.
  • CS8620 - Tento argument nelze použít pro parametr kvůli rozdílům ve schopnosti referenčních typů být null.
  • CS8621 - Nulovost odkazových typů ve vraceném typu se neodpovídá cílovému delegátovi (možná kvůli atributům nulovosti).
  • CS8622 - Nullovatelnost odkazových typů v typu parametru neodpovídá cílovému delegátu (pravděpodobně kvůli atributům nullability).
  • CS8623 - Explicitní použití System.Runtime.CompilerServices.NullableAttribute není povoleno.
  • CS8624 - Argument nelze použít jako výstup kvůli rozdílům v nulovosti referenčních typů.
  • CS8625 - Nelze převést literál null na nenulový odkazový typ.
  • CS8628 - Nelze použít typ odkazu s možnou hodnotou null při vytváření objektu.
  • CS8629: Typ hodnoty s možnou hodnotou null může být null.
  • CS8631 - Typ nelze použít jako parametr typu v obecném typu nebo metodě. Hodnota Nullability argumentu typu neodpovídá typu omezení.
  • CS8632 - Poznámky pro nulovatelné odkazové typy by měly být použity pouze v kódu v kontextu poznámek #nullable.
  • CS8633 - Omezení nulovatelnosti pro parametr typu metody neodpovídají omezením pro parametr typu metody rozhraní. Zvažte použití explicitní implementace rozhraní.
  • CS8634 - Typ nelze použít jako parametr typu v obecném typu nebo metodě. Hodnota Nullability argumentu typu neodpovídá omezení "class".
  • CS8636 - Neplatná možnost pro /nullable; musí být disable, enable, warnings nebo annotations
  • CS8637 - očekávané enable, disablenebo restore
  • CS8639 - Typ operátoru nelze použít u typu odkazu s možnou hodnotou null
  • CS8643 - Nullability odkazových typů ve specifikátoru explicitního rozhraní neodpovídá rozhraní implementovanému typem.
  • CS8644 - Typ neimplementuje člena rozhraní. Nulovatelnost odkazových typů v rozhraní implementovaném základním typem se neshoduje.
  • CS8645 - Člen je již uveden v seznamu rozhraní typu s různou nulovostí referenčních typů.
  • CS8655 - Výraz přepínače nezpracuje některé vstupy null (není vyčerpávající).
  • Deklarace částečné metody CS8667 - mají nekonzistentní nulovou hodnotu v omezeních parametru typu.
  • CS8670 - Objekt nebo inicializátor kolekce implicitně dereferencuje pravděpodobně 'null' člena.
  • CS8714 - Typ nelze použít jako parametr typu v obecném typu nebo metodě. Hodnota Nullability argumentu typu neodpovídá omezení notnull.
  • Parametr CS8762 - musí mít při ukončení hodnotu, která nemá hodnotu null.
  • CS8763Metoda označená jako by se neměla vrátit.
  • CS8764 - Nullability návratového typu neodpovídá přepsanému členu (pravděpodobně kvůli atributům nullability).
  • CS8765 - Nullability typu parametru neodpovídá přepsaného členu (pravděpodobně kvůli atributům nullability).
  • CS8766 - Nullovost odkazových typů ve vráceném typu neodpovídá implicitně implementovanému členu (pravděpodobně kvůli atributům nulovosti).
  • CS8767 - Nullability odkazových typů v typu parametru neodpovídá implicitně implementovanému členu (pravděpodobně kvůli atributům nullability).
  • CS8768 - Nulovatelnost odkazových typů v návratovém typu neodpovídá implementovanému členu (pravděpodobně kvůli atributům nulovatelnosti).
  • Nullovatelnost referenčních typů v typu parametru nevyhovuje implementovanému členu (pravděpodobně kvůli atributům nullovatelnosti).
  • CS8770 - Metoda nemá poznámky [DoesNotReturn] odpovídající implementovanému nebo přepisovanému členu.
  • CS8774 - Člen musí mít při ukončení hodnotu, která nemá hodnotu null.
  • Člen CS8776 - nelze použít v tomto atributu.
  • CS8775 - Člen musí mít při ukončení hodnotu, která nemá hodnotu null.
  • Parametr CS8777 - musí mít při ukončení hodnotu, která nemá hodnotu null.
  • CS8819 - Nulovatelnost odkazových typů v návratovém typu neodpovídá částečné deklaraci metody.
  • Parametr CS8824 - musí mít při ukončení hodnotu, která nemá hodnotu null, protože parametr nemá hodnotu null.
  • Návratová hodnota CS8825 - musí být nenulová, protože parametr nemá hodnotu null.
  • CS8847 - Výraz přepínače nezpracuje některé vstupy null (není vyčerpávající). Vzor s klauzulí when se však může úspěšně shodovat s touto hodnotou.

Poznámka

Statická analýza nemůže vždy odvodit, v jakém pořadí se v určitém scénáři přistupují metody a jestli se metoda úspěšně dokončí bez vyvolání výjimky. Tyto známé nástrahy jsou dobře popsány v oddílu Známé nástrahy.

Téměř všechna upozornění řešíte pomocí jedné z pěti technik:

  • Konfigurace nullovatelného kontextu
  • Přidání nezbytných kontrol nulových hodnot.
  • Přidání nebo odebrání ? nebo ! nullovatelných poznámek.
  • Přidání atributů, které popisují sémantiku null
  • Správná inicializace proměnných.

Pokud s používáním referenčních typů s možnou hodnotou null začínáte, přehled typů odkazů s možnou hodnotou null poskytuje pozadí o tom, jaké typy odkazů s možnou hodnotou null řeší a jak fungují, aby poskytovaly upozornění na možné chyby v kódu. Můžete také zkontrolovat pokyny k migraci na odkazové typy s možnou hodnotou null, další informace o povolení typů odkazů s možnou hodnotou null v existujícím projektu.

Konfigurace kontextu s možnou hodnotou null

Následující upozornění značí, že jste nenastavili správně kontext s možnou hodnotou null:

  • CS8632 - Poznámky pro odkazové typy s možnou hodnotou null by měly být použity pouze v kódu v kontextu #nullable poznámek.
  • CS8636 - Neplatná možnost pro /nullable; musí být disable, enable, warnings nebo annotations
  • CS8637 - očekávané enable, disablenebo restore

Nesprávná syntaxe poznámek

Tyto chyby a upozornění značí, že použití ! nebo ? poznámky není správné.

  • CS8598 - Operátor potlačení není v tomto kontextu povolen
  • CS8623 - Explicitní použití System.Runtime.CompilerServices.NullableAttribute není povoleno.
  • CS8628 - Nelze použít typ odkazu s možnou hodnotou null při vytváření objektu.
  • CS8639 - Operátor typeof nelze použít u nulovatelného referenčního typu

? poznámky v deklaraci označují, že proměnná může mít hodnotu null. Neindikuje jiný typ modulu runtime. Obě následující deklarace jsou stejného typu modulu runtime:

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

? je indikací pro kompilátor ohledně očekávání hodnot null.

! poznámky ve výrazu označují, že víte, že výraz je bezpečný a měl by se předpokládat, že nemá hodnotu null.

  • Tyto poznámky musíte použít, nikoli System.Runtime.CompilerServices.NullableAttribute v kódu.
  • Vzhledem k tomu, že ? je poznámka, nikoli typ, nemůžete ji použít s typeofani new výrazy.
  • Operátor ! nelze použít u výrazu proměnné nebo skupiny metod.
  • Operátor ! nelze použít nalevo od přístupového operátoru člena, například obj.Field!.Method().

Možné dereference hodnoty null

Tato sada upozornění vás upozorní, že dereferencujete proměnnou, jejíž stav null je možná null. Tato upozornění jsou:

  • CS8602 - Dereference pravděpodobně nulového odkazu.
  • CS8670 - Objekt nebo inicializátor kolekce implicitně dereferencuje možná null člen.

Následující kód ukazuje jeden příklad každého z předchozích upozornění:

C#
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
}

V předchozím příkladu je upozornění proto, že Container, cmohou mít hodnotu null pro vlastnost States. Přiřazení nových stavů ke kolekci, která může mít hodnotu null, způsobí upozornění.

Pokud chcete tato upozornění odebrat, je potřeba přidat kód, který změní stav null této proměnné na not-null před jejím dereferencí. Upozornění inicializátoru kolekce může být obtížnější odhalit. Kompilátor zjistí, že kolekce může být null, když do ní inicializátor přidává prvky.

V mnoha případech můžete tato upozornění opravit tím, že zkontrolujete, zda proměnná nemá hodnotu null, než ji dereferencujete. Podívejte se na následující příklad, který před dereferencováním parametru message přidá kontrolu null:

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

Následující příklad inicializuje záložní úložiště pro States objekt a odebere set příslušenství. Uživatelé této třídy mohou upravovat obsah kolekce a paměť pro kolekci není nikdy null:

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

Jiné instance, když se zobrazí tato upozornění, můžou být falešně pozitivní. Možná máte privátní metodu nástroje, která testuje hodnotu null. Kompilátor neví, že metoda poskytuje kontrolu null. Představte si následující příklad, který používá privátní metodu utility: IsNotNull

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

Kompilátor varuje, že při dereferencování může dojít k odkazu na null při zápisu vlastnosti message.Length, protože její statická analýza ukazuje, že message může být null. Víte, že IsNotNull poskytuje kontrolu null a když vrátí true, stav nullmessage by měl být not-null. Kompilátoru musíte sdělit tato fakta. Jedním ze způsobů je použít operátor pro toleranci null, !. Příkaz můžete změnit WriteLine tak, aby odpovídal následujícímu kódu:

C#
Console.WriteLine(message!.Length);

Operátor pro odpuštění null způsobí, že výraz není null i když by byl možná null bez použití !. V tomto příkladu je lepším řešením přidat atribut k podpisu IsNotNull:

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

Informace System.Diagnostics.CodeAnalysis.NotNullWhenAttribute kompilátoru říká, že argument použitý pro parametr obj není null, když metoda vrátí true. Když metoda vrátí false, argument má stejný stav null, který měl předtím, než byla volána metoda.

Tip

Existuje bohatá sada atributů, které můžete použít k popisu, jak vaše metody a vlastnosti ovlivňují stav null. Můžete se o nich dozvědět v článku s referenčními informacemi o nullovatelných atributech statické analýzy.

Oprava upozornění pro dereferencování proměnné typu možná null zahrnuje jednu ze tří technik:

  • Přidejte chybějící kontrolu null.
  • Přidejte atributy null analýzy v API, které ovlivňují statickou analýzu stavu null kompilátoru. Tyto atributy informují kompilátor, pokud by návratová hodnota nebo argument měl být možná null nebo not-null po volání metody.
  • Použijte nulový odpustkový operátor ! na výraz, který vynutí stav není null.

Možnou hodnotu null přiřazenou nenulovatelnému odkazu

Tato sada upozornění vás upozorní, že přiřazujete proměnnou, jejíž typ je nenulovatelný výrazu, jehož stav null je možná null. Tato upozornění jsou:

  • Cs8597 - Vyvolaná hodnota může být null.
  • CS8600 - Převádění null literálu nebo možné nulové hodnoty na nenulový typ.
  • CS8601 - Možné přiřazení odkazu s hodnotou null
  • CS8603 - Možný návrat nulové reference.
  • CS8604 - Možný argument odkazu null pro parametr.
  • CS8605 - Rozbalování možná nulové hodnoty.
  • CS8625 - Nelze převést literál null na nenulový odkazový typ.
  • CS8629 - Nullable typ hodnoty může mít hodnotu null.

Kompilátor vygeneruje tato upozornění při pokusu o přiřazení výrazu možná-null proměnné, která není nullable. Příklad:

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

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

Různá upozornění obsahují podrobnosti o kódu, jako je přiřazení, zrušení přiřazení, návratové příkazy, argumenty metod a vyvolání výrazů.

Pokud chcete tato upozornění vyřešit, můžete provést jednu ze tří akcí. Jedním ze způsobů je přidání anotace ?, aby proměnná byla typu odkazu s možnou hodnotou null. Tato změna může způsobit další upozornění. Změna proměnné z nenulovatelného odkazu na nulovatelný odkaz změní výchozí stav null z not-null na maybe-null. Statická analýza kompilátoru najde instance, kde se dereference proměnné, která je možná null.

Ostatní akce instruují kompilátoru, že pravá strana přiřazení není null. Výraz na pravé straně může být před přiřazením označený hodnotou null, jak je znázorněno v následujícím příkladu:

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

Předchozí příklady ukazují přiřazení návratové hodnoty metody. Metodu (nebo vlastnost) označíte pro indikaci, kdy metoda vrátí hodnotu, která není null. Často System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute určuje, že návratová hodnota není null , pokud vstupní argument není null. Další alternativou je přidat operátor odpouštění nulových hodnot ! na pravou stranu.

C#
string msg = TryGetMessage(42)!;

Oprava upozornění při přiřazení možná-null výrazu do neznull proměnné zahrnuje jednu ze čtyř technik:

  • Změňte levou stranu přiřazení na typ s nulovou hodnotou. Tato akce může při dereferenci této proměnné zavést nová upozornění.
  • Před přiřazením proveďte kontrolu nulové hodnoty.
  • Anotujte rozhraní API, které vytváří pravou stranu přiřazení.
  • Na pravou stranu přiřazení přidejte operátor pro odřazování null.

Nenulovatelný odkaz není inicializován

Tato sada upozornění vás upozorní, že přiřazujete proměnnou, jejíž typ nemá hodnotu null, výrazu, jehož stav null je možná null. Tato upozornění jsou:

  • Cs8618 - Proměnná bez hodnoty null musí při ukončení konstruktoru obsahovat nenulovou hodnotu. Zvažte jeho deklarování jako nullable.
  • Parametr CS8762 - musí mít při ukončení hodnotu, která nemá hodnotu null.

Jako příklad vezměte v úvahu následující třídu:

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

Ani FirstName ani LastName není zaručena jejich inicializace. Pokud je tento kód nový, zvažte změnu veřejného rozhraní. Předchozí příklad lze aktualizovat následujícím způsobem:

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

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

Pokud před nastavením názvu požadujete vytvoření objektu Person , můžete vlastnosti inicializovat pomocí výchozí hodnoty, která není null:

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

Další alternativou je změnit tyto členy na referenční typy, které mohou mít hodnotu null. Třída Person by mohla být definována následujícím způsobem, pokud null by měla být pro název povolena:

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

Existující kód někdy vyžaduje další změny, aby kompilátor informoval o sémantice null pro tyto členy. Může mít více konstruktorů a vaše třída má soukromou pomocnou metodu, která inicializuje jeden nebo více členů. Inicializační kód můžete přesunout do jednoho konstruktoru a zajistit, aby všechny konstruktory volaly ten s běžným inicializačním kódem. Nebo můžete použít atributy System.Diagnostics.CodeAnalysis.MemberNotNullAttribute a System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute. Tyto atributy informují kompilátor, že člen je not-null po vrácení metody. Následující kód ukazuje příklad každého z nich. Třída Person používá společný konstruktor volaný všemi ostatními konstruktory. Třída Student má pomocnou metodu anotovanou atributem System.Diagnostics.CodeAnalysis.MemberNotNullAttribute :

C#

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";
    }
}

Nakonec můžete použít operátor potlačení null k označení, že člen je inicializován v jiném kódu. V jiném příkladu zvažte následující třídy představující model Entity Framework Core:

C#
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!;
}

Vlastnost DbSet je inicializována na null!. To říká kompilátoru, že vlastnost je nastavena na hodnotu not-null . Ve skutečnosti základ DbContext provádí inicializaci sady. Statická analýza kompilátoru to nezachytá. Další informace o práci s odkazovými typy s možnou hodnotou null a Entity Framework Core najdete v článku Práce s odkazovými typy s možnou hodnotou Null v EF Core.

Oprava upozornění na neinicializovaný nenulovatelný člen zahrnuje jednu ze čtyř technik:

  • Změňte konstruktory nebo inicializátory polí, aby se zajistilo, že jsou inicializovány všechny nenulovatelné členy.
  • Změňte jeden nebo více členů na typy s možnou hodnotou null.
  • Označte všechny pomocné metody poznámkami, které označují, které členy jsou přiřazeny.
  • Přidejte inicializátor do null!, aby bylo zřejmé, že člen je inicializován v jiném kódu.

Neshoda v deklaraci nulovatelnosti

Mnoho upozornění naznačuje neshody ohledně nulovatelnosti mezi podpisy pro metody, delegáty nebo parametry typu.

  • CS8608 - Odkazové typy ve typu nemají stejnou nulovatelnost jako přepsaný člen.
  • CS8609 - Nullabilita odkazových typů v návratovém typu neodpovídá přepsanému členovi.
  • CS8610 - Nullabilita odkazových typů v parametrů typu neodpovídá přepsanému členu.
  • CS8611 - Nullability odkazových typů v parametru typu neodpovídá částečné deklaraci metody.
  • CS8612 - Nullabilita odkazových typů neodpovídá implicitně implementovanému členu.
  • CS8613 - Nullovatelnost odkazových typů v návratovém typu neodpovídá implicitně implementovanému členu.
  • CS8614 - Nullability odkazových typů parametru neodpovídá implicitně implementovanému členovi.
  • CS8615 - Nulovatelnost odkazových typů v rámci typu neodpovídá implementovanému členu.
  • CS8616 - Nullability odkazových typů v návratovém typu není shodná s implementovaným členem.
  • CS8617 - Nullovatelnost odkazových typů u parametrů neodpovídá implementovanému členu.
  • CS8619 - Nulovatelnost odkazových typů neodpovídá cílovému typu.
  • CS8620 - Parametr nelze použít kvůli rozdílům v možnosti nulové hodnoty u referenčních typů.
  • CS8621 - Nullable vlastnosti referenčních typů v návratovém typu neodpovídají cílovému delegátu (pravděpodobně kvůli atributům nullable).
  • CS8622 - Nullabilita odkazových typů v typu parametru nesouhlasí s cílovým delegátem (možná kvůli atributům nullability).
  • CS8624 - Argument nelze použít jako výstup kvůli rozdílům v nulovosti referenčních typů.
  • CS8631 - Typ nelze použít jako parametr typu v obecném typu nebo metodě. Hodnota Nullability argumentu typu neodpovídá typu omezení.
  • CS86333 - Nullability v omezeních pro parametr typu metody neodpovídá omezením pro parametr typu metody rozhraní. Místo toho zvažte použití explicitní implementace rozhraní.
  • CS8634 - Typ nelze použít jako parametr typu v obecném typu nebo metodě. Hodnota Nullability argumentu typu neodpovídá omezení "class".
  • CS8643 - Nulovatelnost odkazových typů ve specifikátoru explicitního rozhraní neodpovídá rozhraní implementovanému daným typem.
  • CS8644 - Typ neimplementuje člena rozhraní. Nullovatelnost referenčních typů v rozhraní implementovaném základním typem neodpovídá.
  • CS8645 - Člen je již uveden v seznamu rozhraní pro typ, ale s jinou nulovatelností referenčních typů.
  • Deklarace částečné metody CS8667 - mají nekonzistentní nulovou hodnotu v omezeních parametru typu.
  • CS8714 - Typ nelze použít jako parametr typu v obecném typu nebo metodě. Hodnota Nullability argumentu typu neodpovídá omezení notnull.
  • CS8764 - Nullability návratového typu neodpovídá přepsanému členu (pravděpodobně kvůli atributům nulovatelnosti).
  • CS8765 - Nullability typu parametru neodpovídá přepsaného členu (pravděpodobně kvůli atributům nullability).
  • CS8766 - Možnost nulové hodnoty referenčních typů v návratovém typu neodpovídá implicitně implementovanému členu (pravděpodobně kvůli atributům možnosti nulové hodnoty).
  • CS8767 - Nullovatelnost odkazových typů v typu parametru neodpovídá implicitně implementovanému členu (pravděpodobně kvůli atributům nullovatelnosti).
  • CS8768 - Nulovatelnost odkazových typů v návratovém typu neodpovídá implementovanému členu (pravděpodobně kvůli atributům nulovatelnosti).
  • CS8769 - Nullabilita odkazových typů v typu parametru neodpovídá implementovanému členu (pravděpodobně kvůli atributům nulovatelnosti).
  • CS8819 - Nullabilita odkazových typů v návratovém typu se neshoduje s částečnou deklarací metody.

Následující kód ukazuje CS8764:

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

Předchozí příklad ukazuje metodu virtual v základní třídě a override s odlišnou možností nulové hodnoty. Základní třída vrací řetězec, který nepřipouští hodnotu null, ale odvozená třída vrací řetězec, který připouští hodnotu null. Pokud jsou string a string? obráceny, bylo by to povoleno, protože odvozená třída je více omezující. Podobně by se deklarace parametrů měly shodovat. Parametry v přepsané metodě mohou povolit hodnotu null, i když to základní třída neumožňuje.

Tato upozornění můžou vygenerovat i další situace. V deklaraci metody rozhraní a implementaci této metody došlo k neshodě. Nebo typ delegáta a výraz pro tento delegát se liší. Parametr typu a argument typu se liší v nulovatelnosti.

Chcete-li tato upozornění opravit, aktualizujte příslušnou deklaraci.

Kód neodpovídá deklaraci atributu

V předchozích částech byly probrány způsoby, jak můžete použít Atributy pro nulovatelnou statickou analýzu, aby informovaly kompilátor o sémantice null vašeho kódu. Kompilátor vás upozorní, pokud kód nedodržuje přísliby tohoto atributu:

  • CS8607 - Možnou hodnotu null nelze použít pro typ označený [NotNull] nebo[DisallowNull]
  • CS8763 - Metoda označená [DoesNotReturn] by neměla mít návratovou hodnotu.
  • CS8770 - Metoda nemá poznámky [DoesNotReturn] odpovídající implementovanému nebo přepisovanému členu.
  • CS8774 - Člen musí mít při ukončení hodnotu, která nemá hodnotu null.
  • CS8775 - Člen musí mít při ukončení nenulovou hodnotu.
  • Člen CS8776 - nelze použít v tomto atributu.
  • Parametr CS8777 - musí mít při ukončení hodnotu, která nemá hodnotu null.
  • Parametr CS8824 - musí mít při ukončení hodnotu, která nemá hodnotu null, protože parametr nemá hodnotu null.
  • Návratová hodnota CS8825 - musí být nenulová, protože parametr nemá hodnotu null.

Zvažte následující metodu:

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

}

Kompilátor vytvoří upozornění, protože message parametr je přiřazen nulla metoda vrátí true. Atribut NotNullWhen označuje, že by se nemělo stát.

Pokud chcete tato upozornění vyřešit, aktualizujte kód tak, aby odpovídal očekávání použitým atributům. Můžete změnit atributy nebo algoritmus.

Vyčerpávající výraz přepínače

Výrazy přepínače musí být úplné, což znamená, že vstupní hodnoty musí být zpracovány. I pro odkazové typy, které neakceptují hodnotu null, musí být hodnota null zohledněna. Kompilátor vydává upozornění, když není zpracována hodnota null:

  • CS8655 - Výraz přepínače nezpracuje některé vstupy null (není vyčerpávající).
  • CS8847 - Výraz přepínače nezpracuje některé vstupy null (není vyčerpávající). Vzor s klauzulí when se však může úspěšně shodovat s touto hodnotou.

Následující příklad kódu ukazuje tuto podmínku:

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

Vstupní výraz je , stringnikoli string?. Kompilátor toto upozornění přesto vygeneruje. Vzor { } zpracovává všechny hodnoty, které nejsou null, ale neodpovídají null. Pokud chcete tyto chyby vyřešit, můžete buď přidat explicitní null případ, nebo nahradit { } vzorem _ (zahodit). Vzor zahození kromě jakékoli jiné hodnoty odpovídá hodnotě null.