Běžným hodnotovým typům nelze přiřadit hodnotu null, tu lze přiřadit pouze referenčním typům. Nastává problém, pokud hodnotu null chápeme jako "bez hodnoty" místo "bez odkazu". Hodnota null představuje také jednu z typických hodnot v databázových sloupcích, kde i hodnotové typy mohou mít hodnotu null. C# 2.0 nabízí řešení v podobě typů s hodnotou null nazývané nullable typy.
Nullable typy deklarujeme tak, že využijeme předdefinovanou generickou třídu Nullable<T>, která může uchovat libovolnou hodnotu. Tudíž jak hodnotovou, tak referenční, ale zároveň vždy i hodnotu null.
Existuje také nová syntaxe s operátorem ?, která mimo jiné nahrazuje použití názvu Nullable ve špičatých závorkách na konkrétní typ.
Nullable typy jsou zkonstruovány pomocí typového parametru ?. Například int? je nullable forma předdefinovaného typu int. Základní typ nullable typů může být pouze hodnotový typ, který není typu nullable. Nullable typ je struktura, která kombinuje hodnotu základního typu s booleovským indikátorem null. Instance nullable typu má dvě neměnné, veřejné vlastnosti:
HasValue, typu bool. HasValue je true pro instance, které neposkytují hodnotu typu null a false pro null instance.
Value, má typ podle základního typu nullable typu. Vrací obsažený typ, když HasValue je true. V opačném případě, když je HasValue false, při pokusu o zpřístupnění jejího obsahu vyvolá výjimku.
Existuje také implicitní konverze z jakéhokoliv non-nullable hodnotového typu na nullable formu tohoto typu. Dále také existuje implicitní konverze z literálu null, na kterýkoliv nullable typ. Více v příkladu níže:
int? x = 123; int? y = null; if (x.HasValue) Console.WriteLine(x.Value); if (y.HasValue) Console.WriteLine(y.Value); |
Hodnota 123 typu int a literál null jsou při deklaraci implicitně přetypovány na nullable typ int?. Výstup na obrazovku bude proveden pouze pro proměnnou x, jejíž booleovská hodnota metody HasValue je true, neboť x obsahuje non-nullable hodnotu. Proto se proměnná y nevypíše, neb neprojde přes podmínku příkazu if.
Další ukázka deklarací využívajících nullable konverze:
int i = 123; int? x = i; // int --> int? double? y = x; // int? --> double? int? z = (int?)y; // double? --> int? int j = (int)z; // int? --> int |
Uživatelem definovaný operátor konverze má větší prioritu, když nastane situace, že zdroj i cíl konverze jsou nullable hodnotové typy.