2011. március 11., péntek

Ilyen a box...

Mit ír ki?

Nullable<int> ni = 42;
Console.WriteLine(ni.GetType().FullName);

6 megjegyzés:

  1. Mennyivel viccesebb, ha null-t adunk értékül.

    VálaszTörlés
  2. Persze, mivel a GetType() a System.Object függvénye, és a System.Object referencia típus, a GetType() implementációja mindenképpen vár egy this pointert első paraméterként, és erről a pointerről feltételezi, hogy olyan adatszerkezetre mutat, ami pedig a referencia típusokra jellemző, pl a this által mutatott memóriaterületen ott van a type handle.
    Mivel ez csak a referencia típusokra jellemző, az értéktípusokra nem, emiatt kénytelen a CLR elvégezni a boxingot, hogy normális this pointert adhasson át a GetType()-nak.
    A Nullable típusok boxingja viszont meg van patkolva. Bár hirtelen ránézésből az lenne logikus, ha szokásos módon, a boxing átmásolná a teljes Nullable adatszerkezetet a heap-re, és a Nullable type handle-jét rakná elé, a referencia típusok esetében a Nullable által bevezetett feature-nek nincsen semmi értelme. Gondoljunk bele, hogy milyen zavar van itt: egyrészt logikai szempontból egy Nullable lehet null úgy, hogy a HasValue false. Másrészt Boxing után úgy is lehet null a dobozolt értékre "mutató" referencia, hogy az ő értéke szintén null. Tehát két eszköz lenne egy Boxingolt Nullable null értékének kifejezésére.
    Látszik, hogy a Nullable.HasValue() nak nincs értelme a dobozolt érték esetében, mert kiváltható egy szimpla null referenciával. Ezek miatt van, hogy a Nullable-k esetében csak a hordozott érték kerül "dobozolásra", illetve ha a Nullable logikailag null, akkor a boxing szimplán egy null referenciát ad vissza, nem is csinálja meg a boxingot. Ez ki is próbálható a következő programmal:

    for (int n = 0; n < 10000000; n++)
    {
    Nullable i = null; // = 42
    object o = i;
    }

    Console.WriteLine(GC.CollectionCount(0));

    A fenti program, ha null-t kap i, akkor nincs GC, egyébként meg van pár. Cserében viszont Nullable-re mindent lehet unboxolni, akár nullable-ből származik a boxingol érték, akár nem:

    Nullable no;
    object o = null;
    object o2 = 12;
    no = (Nullable)o;
    Console.WriteLine(no.HasValue);
    no = (Nullable)o2;
    Console.WriteLine(no.HasValue);

    VálaszTörlés
  3. Viktor, a google valamiert spamnek nezte a kommented. Pedig korantsem az. :)
    Meg jo, h kuldott rola emailt.

    VálaszTörlés
  4. egyebkent gratula a blogodboz, nagyon jo irasaid vannak!

    VálaszTörlés