Bezpečnost null v jazyce C#

Tip

Tento článek je součástí části Základy pro vývojáře, kteří už znají aspoň jeden programovací jazyk a učí se jazyk C#. Pokud s programováním teprve začínáte, začněte nejprve kurzy Začínáme .

Pocházíte z Java nebo C++? Jazyk C# poskytuje zabezpečení proti hodnotám null v době kompilace prostřednictvím nullable referenčních typů. Cíl je podobný @NonNull poznámek Java, ale vynucuje ho kompilátor. Jazyk C# má také vyhrazené operátory, jako ?. a ??, které zkracují výrazy bezpečné proti hodnotě null.

null představuje nepřítomnost hodnoty. Když se pokusíte získat přístup k členu null v odkazu voláním metody nebo čtením vlastnosti, modul runtime vyvolá NullReferenceException:

// Accessing a member on null throws NullReferenceException at runtime:
// string? name = null;
// int length = name.Length; // throws NullReferenceException

// Check before you dereference:
string? name = null;
if (name is not null)
{
    Console.WriteLine($"Name has {name.Length} characters.");
}
else
{
    Console.WriteLine("Name has no value.");
}
// Output: Name has no value.

Jazyk C# poskytuje tři doplňkové nástroje pro zápis kódu bezpečného s hodnotou null:

  • Typy hodnot s možnou hodnotou null: umožněte typu hodnoty, například int nebo bool, také obsahovat null
  • Typy odkazů s možnou hodnotou null: umožňuje kompilátoru sledovat, jestli může být odkaz null
  • Operátory null: jako stručný přístup pro bezpečné zpracování nulových hodnot a přechod na náhradní logiku

Typy nulovatelných hodnot

Typy hodnot, jako jsou int, double a bool, nemohou ve výchozím nastavení uchovávat null. Přidejte ? do názvu typu, abyste vytvořili nulovatelný typ hodnoty, který obsahuje buď hodnotu, nebo null:

int? score = null;
Console.WriteLine(score.HasValue);               // False

score = 95;
Console.WriteLine(score.HasValue);               // True
Console.WriteLine(score.GetValueOrDefault());    // 95

int? missing = null;
Console.WriteLine(missing.GetValueOrDefault(-1)); // -1

Typy hodnot s možnou hodnotou null jsou užitečné, když základní typ hodnoty musí představovat "žádná data". Mezi běžné scénáře patří databázové sloupce, které nemusí chybět, volitelná nastavení konfigurace a čtení ze senzorů, které ještě nejsou zachyceny.

Úplné pokrytí deklarací, kontroly a převodu naleznete v části Typy hodnot s možnou hodnotou Null.

Nulovatelné odkazové typy

Referenční typy, jako jsou string, pole a instance tříd, mohou za běhu obsahovat null. Odkazové typy s možnou hodnotou null jsou funkcí kompilátoru, která dělají záměr použití null explicitním a rozpoznávají chyby v době kompilace.

Pomocí poznámky ? deklarujete svůj záměr:

  • string? — tento odkaz může být null; kompilátor varuje, pokud jej předeferujete bez první kontroly.
  • string— tento odkaz by neměl být null; kompilátor varuje, pokud k němu přiřadíte null
// string?  means this reference might be null
// string   means this reference should not be null
string? nullableName = null;
string  nonNullName  = "Alice";

// ?. safely accesses a member when the reference might be null
string display = nullableName?.ToUpper() ?? "(no name)";
Console.WriteLine(display);         // (no name)

display = nonNullName.ToUpper();    // safe: nonNullName is never null
Console.WriteLine(display);         // ALICE

Všechny projekty .NET, které moderní šablony SADY SDK ve výchozím nastavení vytvářejí, umožňují odkazové typy s možnou hodnotou null. Úplné pokyny k povolení a přidávání poznámek najdete v referenčních typech s možnou hodnotou Null.

Operátory null

C# obsahuje několik operátorů, které umožňují psát kód bezpečný vůči null bez ručního použití kontrolních podmínek null všude:

Operator Name Purpose
?. Přístup podmíněného člena s hodnotou null Přístup k členu pouze v případech, kdy objekt není null
?[] Přístup k podmíněnému indexeru s hodnotou null Přístup k elementu pouze v případech, kdy kolekce nemá hodnotu null
?? Souhlásání s hodnotou null Vrácení záložní hodnoty, pokud je výraz null
??= Přiřazení při souhlásání s hodnotou null Přiřadit pouze v případech, kdy je proměnná null
is null / is not null Nulový vzor Upřednostňovaný test s hodnotou null
string? city = GetCity();

// ?. — access a member only when non-null
int? len = city?.Length;

// ?? — substitute a default when null
string display = city ?? "unknown";

// is null — preferred null test
if (city is null)
{
    Console.WriteLine("No city provided.");
}
else
{
    Console.WriteLine($"{display} ({len} chars)");
}
// Output: No city provided.

Podrobné příklady jednotlivých operátorů naleznete v tématu Nulové operátory.

Typy hodnot s možnou hodnotou null a odkazové typy s možnou hodnotou null slouží různým účelům.

Typy hodnot s možnou hodnotou null a odkazové typy s možnou hodnotou null nejsou alternativy. Řeší různé problémy:

  • Slouží T? pro typ hodnoty, který musí představovat "žádná hodnota". Můžete například použít int? volitelný databázový sloupec nebo DateTime? událost, která ještě není naplánovaná.
  • Pomocí string? a dalších poznámek s možnou hodnotou null můžete dokumentovat, že odkaz může být null, takže kompilátor vás může upozornit před výskytem NullReferenceException za běhu.

Společně vám tyto funkce a operátory null poskytují kompletní sadu nástrojů pro zápis kódu C# bezpečného s hodnotou null.