Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Poznámka:
Tento článek popisuje odkazové typy s možnou hodnotou null. Můžete také deklarovat typy hodnot s možnou hodnotou null.
V kódu, který je v kontextu s možnou hodnotou null, použijte odkazové typy s možnou hodnotou null. Odkazové typy s možnou hodnotou null, upozornění statické analýzy null a operátor null-forgiving jsou volitelné jazykové funkce. Ve výchozím nastavení jsou všechny vypnuté. Kontext s možnou hodnotou null můžete řídit na úrovni projektu pomocí nastavení sestavení nebo kódu pomocí pragmas.
Referenční dokumentace jazyka C# dokumentuje naposledy vydané verze jazyka C#. Obsahuje také počáteční dokumentaci k funkcím ve verzi Public Preview pro nadcházející jazykovou verzi.
Dokumentace identifikuje všechny funkce, které byly poprvé představeny v posledních třech verzích jazyka nebo v aktuálních verzích Public Preview.
Návod
Informace o tom, kdy byla funkce poprvé představena v jazyce C#, najdete v článku o historii verzí jazyka C#.
Důležité
Všechny šablony projektu umožňují kontextu s možnou hodnotou null projektu. Projekty vytvořené pomocí dřívějších šablon tento prvek nezahrnují a tyto funkce jsou vypnuté, pokud je v souboru projektu nepovolíte nebo nepoužijete pragmas.
V kontextu s možnou hodnotou null:
- Je nutné inicializovat proměnnou typu odkazu
Ts hodnotou, která není null, a nikdy nemůžete přiřadit hodnotu, která by mohla býtnull. - Proměnnou typu odkazu
T?můžete inicializovat pomocínullnebo přiřaditnull, ale před dereferencováním ji musíte zkontrolovatnull. - Pokud použijete operátor null-progiving na proměnnou
mtypuT?, jako vm!, proměnná se považuje za nenulovou.
Kompilátor vynucuje rozdíly mezi nenulovým odkazovým typem T a typem T? odkazu s možnou hodnotou null pomocí předchozích pravidel. Proměnná typu T a proměnná typu T? jsou stejného typu .NET. Následující příklad deklaruje nenulový řetězec a řetězec s možnou hodnotou null a potom pomocí operátoru null-forgiving přiřadí hodnotu k řetězci, který není nullable:
string notNull = "Hello";
string? nullable = default;
notNull = nullable!; // null forgiveness
Proměnné notNull i nullable oba používají String typ. Vzhledem k tomu, že typy s možnou hodnotou null a s možnou hodnotou null používají stejný typ, nemůžete použít odkaz s možnou hodnotou null v několika umístěních. Obecně nelze použít odkazový typ s možnou hodnotou null jako základní třídu nebo implementované rozhraní. V žádném objektovém vytvoření nebo testovacím výrazu typu nelze použít odkaz s možnou hodnotou null. Jako typ přístupového výrazu člena nemůžete použít odkaz s možnou hodnotou null. Následující příklady ukazují tyto konstrukce:
public MyClass : System.Object? // not allowed
{
}
var nullEmpty = System.String?.Empty; // Not allowed
var maybeObject = new object?(); // Not allowed
try
{
if (thing is string? nullableString) // not allowed
Console.WriteLine(nullableString);
} catch (Exception? e) // Not Allowed
{
Console.WriteLine("error");
}
Odkazy s možnou hodnotou null a statická analýza
Příklady v předchozí části ilustrují povahu referenčních typů s možnou hodnotou null. Odkazové typy s možnou hodnotou null nejsou nové typy tříd, ale spíše poznámky k existujícím typům odkazů. Kompilátor tyto poznámky používá k nalezení potenciálních chyb odkazu null ve vašem kódu. Neexistuje žádný rozdíl mezi nenulovým odkazovým typem a typem odkazu s možnou hodnotou null. Kompilátor nepřidá žádnou kontrolu za běhu pro nenulové odkazové typy. Výhody jsou v analýze doby kompilace. Kompilátor generuje upozornění, která vám pomůžou najít a opravit potenciální chyby null v kódu. Deklarujete svůj záměr a kompilátor vás upozorní, když váš kód tento záměr porušuje.
Důležité
Poznámky odkazu s možnou hodnotou null nezavádějí změny chování, ale jiné knihovny můžou použít reflexi k vytvoření jiného chování modulu runtime pro odkazové typy s možnou hodnotou null a nenulovou. Entity Framework Core zejména čte atributy s možnou hodnotou null. Interpretuje odkaz s možnou hodnotou null jako volitelnou hodnotu a nenulový odkaz jako požadovanou hodnotu.
V kontextu s povolenou hodnotou null kompilátor provádí statickou analýzu proměnných libovolného typu odkazu, a to jak s možnou hodnotou null, tak bez hodnoty null. Kompilátor sleduje stav null každé referenční proměnné jako buď not-null , nebo možná-null. Výchozí stav odkazu bez hodnoty null není null. Výchozí stav odkazu s možnou hodnotou null je možná null.
Odkazové typy bez null by vždy měly být bezpečné pro dereference, protože jejich stav null není null. Pokud chcete toto pravidlo vynutit, kompilátor vydá upozornění, pokud není typ odkazu s možnou hodnotou null inicializován na hodnotu, která není null. Musíte přiřadit místní proměnné, kde je deklarujete. Každé pole musí mít přiřazenou hodnotu not-null v inicializátoru pole nebo každém konstruktoru. Kompilátor vydává upozornění, když je odkaz s možnou hodnotou null přiřazený k odkazu, jehož stav je možná null. Obecně platí, že nenulový odkaz není null a při dereferenci těchto proměnných se nevystavují žádná upozornění.
Poznámka:
Pokud přiřadíte výraz s možnou hodnotou null k nenulovatelnému typu odkazu, kompilátor vygeneruje upozornění. Kompilátor pak vygeneruje upozornění pro danou proměnnou, dokud není přiřazený k výrazu not-null .
Můžete inicializovat nebo přiřadit k referenčním typům s možnou hodnotou null null. Proto statická analýza musí před dereferencem určit, že proměnná nemá hodnotu null . Pokud je odkaz s možnou hodnotou null určen jako null, přiřaďte ho proměnné odkazu, která není nullable, vygeneruje upozornění kompilátoru. Následující třída ukazuje příklady těchto upozornění:
public class ProductDescription
{
private string shortDescription;
private string? detailedDescription;
public ProductDescription() // Warning! shortDescription not initialized.
{
}
public ProductDescription(string productDescription) =>
this.shortDescription = productDescription;
public void SetDescriptions(string productDescription, string? details=null)
{
shortDescription = productDescription;
detailedDescription = details;
}
public string GetDescription()
{
if (detailedDescription.Length == 0) // Warning! dereference possible null
{
return shortDescription;
}
else
{
return $"{shortDescription}\n{detailedDescription}";
}
}
public string FullDescription()
{
if (detailedDescription == null)
{
return shortDescription;
}
else if (detailedDescription.Length > 0) // OK, detailedDescription can't be null.
{
return $"{shortDescription}\n{detailedDescription}";
}
return shortDescription;
}
}
Následující fragment kódu ukazuje, kde kompilátor generuje upozornění při použití této třídy:
string shortDescription = default; // Warning! non-nullable set to null;
var product = new ProductDescription(shortDescription); // Warning! static analysis knows shortDescription maybe null.
string description = "widget";
var item = new ProductDescription(description);
item.SetDescriptions(description, "These widgets will do everything.");
Předchozí příklady ukazují, jak statická analýza kompilátoru určuje stav null referenčních proměnných. Kompilátor používá pravidla jazyka pro kontroly a přiřazení null, aby informoval svou analýzu. Kompilátor nemůže předpokládat sémantiku metod nebo vlastností. Pokud voláte metody, které provádějí kontroly null, kompilátor nemůže tyto metody znát vliv na stav null proměnné. Do rozhraní API můžete přidat atributy, které kompilátoru informují o sémantice argumentů a návratových hodnotách. Mnoho běžných rozhraní API v knihovnách .NET má tyto atributy. Kompilátor například správně interpretuje IsNullOrEmpty jako kontrolu null. Další informace o atributech, které platí pro statickou analýzu stavu null, najdete v článku o atributech s možnou hodnotou Null.
Kontext s možnou hodnotou null
Kontext s možnou hodnotou null určuje, jak kompilátor zpracovává poznámky typu odkaz s možnou hodnotou null a jaká upozornění vytváří během statické analýzy stavu null. Kontext s možnou hodnotou null obsahuje dva příznaky: nastavení anotační a nastavení výstrahy.
Nastavení poznámek i upozornění jsou u stávajících projektů ve výchozím stavu zakázaná. Počínaje verzí .NET 6 (C# 10) jsou oba příznaky ve výchozím nastavení zapnuty pro nové projekty. Důvodem dvou odlišných příznaků pro nullable kontext je zjednodušit migraci velkých projektů, které existují před zavedením nullable referenčních typů.
U malých projektů můžete povolit odkazové typy s možnou hodnotou null, opravit upozornění a pokračovat. U větších projektů a víceprojektových řešení ale tento proces může generovat velký počet upozornění. Můžete použít pragmas k povolení odkazových typů s možnou hodnotou null po jednotlivých souborech, jakmile začnete používat nullable reference types. Nové funkce, které chrání před vyvoláním System.NullReferenceException , můžou být při zapnutí v existujícím základu kódu rušivé:
- Všechny explicitní odkazové proměnné jsou interpretovány jako odkazové typy bez hodnoty null.
- Význam omezení
classv obecných typech se změnil tak, že nyní znamená nenulový referenční typ. - Kvůli těmto novým pravidlům se generují nová upozornění.
Kontext poznámek s možnou hodnotou null určuje chování kompilátoru. Existují čtyři kombinace nastavení u kontextu s hodnotou null:
- Oba jsou zakázány: Kód je ignorující null hodnotu.
Zakázat odpovídá chování před zapnutím odkazových typů s možnou hodnotou null, kromě toho, že nová syntaxe místo chyb vytváří upozornění.
- Varování o nulovatelnosti jsou deaktivována.
- Všechny proměnné typu odkazu jsou odkazové typy s možnou hodnotou null.
- Použití přípony
?k deklaraci typu odkazu s možnou hodnotou null vytvoří upozornění. - Můžete použít operátor pro odpouštění null,
!ale nemá žádný vliv.
-
povolené: Kompilátor povolí všechny analýzy nulových odkazů a všechny jazykové prvky.
- Jsou povolena všechna nová upozornění s možnou hodnotou null.
- Příponu
?můžete použít k deklaraci typu odkazu s možnou hodnotou null. - Proměnné typu odkazu bez
?přípony jsou odkazové typy bez hodnoty null. - Operátor pro tolerování null potlačí upozornění pro možnou dereferenci
null.
-
upozornění povoleno: Kompilátor provede veškerou analýzu null a vygeneruje upozornění, kdy může dojít k dereferencování
null.- Jsou povolena všechna nová upozornění s možnou hodnotou null.
- Použití přípony
?k deklaraci typu odkazu s možnou hodnotou null vytvoří upozornění. - Všechny proměnné typu odkazu mohou mít hodnotu null. Členové však mají null-stavne-null na začátku složené závorky všech metod, pokud nejsou deklarováni s příponou
?. - Můžete použít operátor promíjející nulovou hodnotu,
!.
-
povoleny poznámky: Kompilátor nevysílá upozornění, když kód může převést
null, nebo když přiřadíte výraz s možnou hodnotou null proměnné, která není null.- Všechna nová upozornění s možnou hodnotou null jsou zakázaná.
- Příponu
?můžete použít k deklaraci typu odkazu s možnou hodnotou null. - Proměnné typu odkazu bez
?přípony jsou odkazové typy bez hodnoty null. - Můžete použít operátor pro odpouštění null,
!ale nemá žádný vliv.
Kontext poznámek s možnou hodnotou null a kontext upozornění s možnou hodnotou null pro projekt můžete nastavit pomocí elementu<Nullable> v souboru .csproj. Tento element konfiguruje, jak kompilátor interpretuje hodnotu nullability typů a jaká upozornění generuje. Následující tabulka ukazuje povolené hodnoty a shrnuje kontexty, které zadávají.
| Context | Upozornění na dereference | Upozornění přiřazení | Typy odkazů |
? přípona |
! operátor |
|---|---|---|---|---|---|
disable |
Disabled | Disabled | Všechny jsou nulovatelné. | Vyvolá upozornění. | Nemá žádný vliv |
enable |
Enabled | Enabled | Nenulové, pokud není deklarováno pomocí ? |
Deklaruje typ s možnou hodnotou null. | Potlačí možná upozornění při přiřazení null. |
warnings |
Enabled | Nelze použít | Všechny jsou nullable, ale členy jsou považovány za nenulové při otevření složené závorky metod. | Vyvolá upozornění. | Potlačí možná upozornění při přiřazení null. |
annotations |
Disabled | Disabled | Nenulové, pokud není deklarováno pomocí ? |
Deklaruje typ s možnou hodnotou null. | Nemá žádný vliv |
Proměnné typu odkazu v kódu zkompilované v zakázaném kontextu jsou neplatné. Literál null nebo proměnnou s možnou hodnotou null můžete přiřadit proměnné, která je zamlžená. Výchozí stav proměnné s možnou hodnotou null však není null.
Zvolte nastavení, které nejlépe vyhovuje vašemu projektu:
- Zvolte zakázat starší projekty, které nechcete aktualizovat na základě diagnostiky nebo nových funkcí.
- Zvolte upozornění a určete, kde může kód vyvolat System.NullReferenceException. Tato upozornění můžete vyřešit před úpravou kódu, abyste povolili odkazové typy bez hodnoty null.
- Zvolte poznámky k vyjádření vašeho záměru návrhu před povolením upozornění.
- Zvolte povolit pro nové a aktivní projekty, u kterých se chcete chránit před výjimkami s odkazem na hodnotu null.
Příklad :
<Nullable>enable</Nullable>
Direktivy můžete také použít k nastavení těchto stejných příznaků kdekoli ve zdrojovém kódu. Tyto direktivy jsou nejužitečnější při migraci velkého základu kódu.
-
#nullable enable: Nastaví příznaky poznámek a upozornění na povoleno. -
#nullable disable: Nastaví příznaky poznámek a upozornění pro deaktivaci. -
#nullable restore: Obnoví příznak poznámky a příznak upozornění do nastavení projektu. -
#nullable disable warnings: Nastaví příznak upozornění, který chcete zakázat. -
#nullable enable warnings: Nastaví příznak upozornění, který chcete povolit. -
#nullable restore warnings: Obnoví příznak upozornění do nastavení projektu. -
#nullable disable annotations: Nastaví příznak poznámky tak, aby se zakázal. -
#nullable enable annotations: Nastaví příznak poznámky, který chcete povolit. -
#nullable restore annotations: Obnoví značku poznámky v nastavení projektu.
Pro libovolný řádek kódu můžete nastavit některou z následujících kombinací:
| Příznak upozornění | Příznak poznámky | Use |
|---|---|---|
| Výchozí nastavení projektu | Výchozí nastavení projektu | Výchozí |
| povolit | vypnout | Odstraňte varování analýzy |
| povolit | Výchozí nastavení projektu | Odstraňte varování analýzy |
| Výchozí nastavení projektu | povolit | Přidání typových anotací |
| povolit | povolit | Kód už migrovaný |
| vypnout | povolit | Označte kód poznámkami před opravou upozornění |
| vypnout | vypnout | Přidání staršího kódu do migrovaného projektu |
| Výchozí nastavení projektu | vypnout | Zřídka |
| vypnout | Výchozí nastavení projektu | Zřídka |
Tyto devět kombinací poskytují jemně odstupňovanou kontrolu nad diagnostikou, kterou kompilátor generuje pro váš kód. V jakékoli oblasti, kterou aktualizujete, můžete povolit další funkce, aniž byste viděli další upozornění, která ještě nejste připravení řešit.
Důležité
Globální kontext s možnou hodnotou null se nevztahuje na vygenerované soubory kódu. V obou strategiích je kontext s možnou hodnotou null zakázán pro jakýkoli zdrojový soubor označený jako vygenerovaný. Tato podmínka znamená, že kompilátor nenotuje žádná rozhraní API ve vygenerovaných souborech. Kompilátor negeneruje upozornění s možnou hodnotou null pro vygenerované soubory. Soubor se označí jako vygenerovaný některým z následujících čtyř způsobů:
- V souboru .editorconfig zadejte
generated_code = truev oddílu, který se vztahuje na tento soubor. - Umístěte
<auto-generated>nebo<auto-generated/>do komentáře v horní části souboru. Může být na libovolném řádku v daném komentáři, ale blok komentáře musí být prvním prvkem v souboru. - Začněte název souboru s TemporaryGeneratedFile_
- Ukončete název souboru jako .designer.cs, .generated.cs, .g.cs nebo .g.i.cs.
Generátory se můžou přihlásit pomocí direktivy preprocesoru #nullable .
Ve výchozím nastavení jsou příznaky poznámek s možnou hodnotou null a upozornění zakázány. Výchozí hodnota znamená, že váš existující kód se zkompiluje beze změn a bez generování nových upozornění. Počínaje rozhraním .NET 6, nové projekty ve všech šablonách zahrnují prvek <Nullable>enable</Nullable>, přičemž tyto příznaky jsou nastaveny na povoleno.
Tyto možnosti poskytují dvě odlišné strategie aktualizace existujícího základu kódu tak, aby používaly odkazové typy s možnou hodnotou null.
Nastavení kontextu s možnou hodnotou null
Kontext s možnou hodnotou null můžete řídit dvěma způsoby. Na úrovni projektu přidejte <Nullable>enable</Nullable> nastavení projektu. Do jednoho zdrojového souboru jazyka C# přidejte direktivu #nullable enable pragma, která povolí kontext s možnou hodnotou null. Další informace najdete v tématu Nastavení strategie s možnou hodnotou null. Před .NET 6 používají nové projekty výchozí <Nullable>disable</Nullable>. Počínaje rozhraním .NET 6 zahrnují <Nullable>enable</Nullable> nové projekty prvek v souboru projektu.
Generika
Pokud použijete parametr typu, Tjako jeho protějšk s možnou hodnotou null, T?skutečný typ argument určuje způsob ? interpretace. Zvažte následující obecnou deklaraci:
public class Box<T>
{
public T Contents { get; set; }
}
Protože parametr typu může stát buď pro typ odkazu nebo typ hodnoty, význam T? závisí na tom, který argument typu volající dodává. Následující pravidla popisují, co T? se řeší, když T nemá žádná omezení:
- Argument typu je nenulový odkazový typ.
TstringJeBox<string>aT?jestring?– odpovídající typ odkazu s možnou hodnotou null. - Argument typu je typ hodnoty. Pro
Box<int>,TjeintaT?je takéint– stejný typ hodnoty. Poznámka nemá žádný vliv na typy hodnot, pokud parametr typu nemástructomezení, v takovém případěT?znamená Nullable<T> (int?). - Argument typu je již nullable. Pro
Box<string?>,Tjestring?aT?je stálestring?. Nezískáte "doubly nullable" typ.
Omezení omezují, které argumenty typu jsou povolené. Umožňují také kompilátoru zjistit, jak T se dá použít:
-
where T : classvyžaduje odkazový typ bez hodnoty null.Box<string>je povoleno;Box<string?>vytvoří upozornění. -
where T : class?umožňuje odkaz s možnou hodnotou null nebo nenulový odkaz. OběBox<string>aBox<string?>jsou povoleny. -
where T : structvyžaduje typ hodnoty bez hodnoty null.Box<int>je povoleno;Box<int?>Není. S tímto omezením uvnitřT?obecných prostředků Nullable<T>— proBox<int>,T?jeint?. -
where T : notnullvyžaduje nenulový odkaz nebo typ hodnoty.Box<string>aBox<int>jsou povoleny,Box<string?>vytvoří upozornění. -
where T : BaseTypevyžaduje odkazový typ, který není nullable, který je odvozen odBaseType. Připojte (where T : BaseType?) a povolte?také odvozené typy s možnou hodnotou null.
Omezení pomáhají kompilátoru z důvodu, jak se používá parametr obecného typu:
public static T? FirstOrDefault<T>(IEnumerable<T> source)
{
foreach (T item in source)
{
return item;
}
return default;
}
public static void RequireNotNull<T>(T value) where T : notnull
{
ArgumentNullException.ThrowIfNull(value);
}
public static void Generics()
{
string? first = FirstOrDefault<string>([]);
Console.WriteLine(first ?? "<empty>");
RequireNotNull("not null");
}
specifikace jazyka C#
Další informace naleznete v části Typy odkazů s možnou hodnotou Nullspecifikace jazyka C#.