30.10.2011 13:21

System.Nullable

Jak jistě víte, každému objektu v C#u lze přiřadit hodnotu null. Klíčové slovo null označuje nulovou referenci. Instance všech tříd se předávají jen jako odkaz na ně. Null tedy znamená, že odkaz neukazuje nikam (má hodnotu 0). Jinak je to u struktur, ty se nepředávají jako reference, ale jako hodnota. Z toho důvodu není možné jim přímo nastavit hodnotu null.

Tuto (ne)výhodu lze obejít využitím generického typu System.Nullable, kde pro T platí omezení struktury. Tento speciální typ umožní,  aby šlo nastavovat null i instancím struktur. Jeho zkratka je také T?.

public static void Main(string[] args)
{
    bool? x = true; //Totéž, co Nullable<bool> x = true;

    Console.WriteLine(x==null);
    x = null;
    Console.WriteLine(x==null);
    Console.ReadKey(true);
}

Tento kód vytvoří nulovatelný typ bool s počáteční hodnotou true a vypíše, zda se instance rovná null, stejného efektu bychom dosáhli zjištěním a negací vlastnosti HasValue.

Tento typ je speciální i v tom, že ačkoliv je sám o sobě struktura, jde mu přiřadit hodnota null. Ve skutečnosti se mu pouze nastaví nějaké pole, jestli hodnotu obsahuje, na false. Tento typ je zároveň schopen přepsat metodu GetType tak, že se zavolá na skutečnou hodnotu, kterou obsahuje. Pokud se zavolá metoda ToString, vrátí se prázdný řetězec, pokud není přiřazena žádná hodnota, nebo vrátí ToString na hodnotě samotné. Mění také operátory přetypování, takže pokud ho zaboxujeme, výsledná reference bude skutečně null. Za pozornost stojí také metoda GetValueOrDefault, která, pokud je hodnota přiřazena, vrátí hodnotu samotnou, v opačném případě vrátí výchozí hodnotu jejího typu (default(T)). Pokud budeme porovnávat hodnoty typů T? i T, bude porovnání stejné jako kdybychom porovnávali skutečnou hodnotu.

class Clovek
{
    private int? _vek;

    public int Vek
    {
        get{
            if(_vek.HasValue)
            {
                return _vek.Value;
            }else{
                throw new InvalidOperationException("Věk není přiřazen.");
            }
        }
        set{
            _vek = value;
        }
    }
}

Pokud vlastnost Vek není přiřazena, při pokusu o její získání třída vyhodí vyjímku. this._vek.HasValue /*nebo*/ this._vek != null zjistí, jestli je hodnota přiřazena.

—————

Zpět


Diskusní téma: System.Nullable

Nebyly nalezeny žádné příspěvky.