Keresés

Új hozzászólás Aktív témák

  • Alexios

    veterán

    válasz pmonitor #10083 üzenetére

    A fő probléma azzal van hogy a referencia típus fogalmát kevered az object-el.
    Pusztán az hogy az értéktípusok is az object-ből származnak végső soron(nem nehéz amúgy ezt belátni, nem véletlen ignoráltad gondolom a kód példámat is, de ugyanúgy elérhető minden metódus egy int-en is ami egy objectben van, csak hogy még szemléletesebb legyen, ha már a language specet teljesen ignorálod), nem jelenti azt hogy ettől a heap-ben vannak tárolva. Pont ez a System.ValueType lényege, ennek köszönhetően vannak értéktípusként kezelve. Tehát az hogy a System.ValueType-ból származik, nem jelenti hogy ez egy referencia típus, hiszen pont a System.ValueType miatt lesz értéktípus, de ettől az még az objectből származik. Ha pl. egy intet objectként kezelsz akkor jön a boxing, hiszen referencia típusként akarod kezelni(itt is látszik hogy az object az ősosztályuk amúgy, hiszen simán átadhatsz egy intet mondjuk egy metódusnak ami objectet vár, mindenféle compiler error).
    Kicsit olyan ez inkább mintha egy ősosztályán át hivatkoznál egy példányra, ott sem érheted el a metódus/propertyk stb amik a leszármazott osztályban vannak, érték típusoknál meg ha objectként hivatkozol rá akkor jön a boxing, és "elveszted" a leszármazott érték típus tulajdonságokat.(ez csak egy analógia, nem a pontos mechanizmus a kötekvést elkerülendő)

  • pmonitor

    aktív tag

    válasz pmonitor #10083 üzenetére

    Ha jól emléxem, akkor már többször linkeltem be ezt a linket. Ez a másik fórumról való. Ott oldottam meg. Maga a kód(ami nem működik:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace GenericTest
    {
    interface ITorol
    {
    void delete();
    }

    class GenerikusTipus<T>
    {
    T adat;

    public GenerikusTipus(T adat)
    {
    this.adat = adat;
    }

    public T GetErtek()
    {
    return adat;
    }

    public void TorlunkHaTudja()
    {
    if (adat is ITorol)
    (adat as ITorol).delete();
    }
    }

    struct Valami : ITorol
    {
    public int ertek;

    public Valami(int ertek)
    {
    this.ertek = ertek;
    }

    public void delete()
    {
    ertek = 0;
    }

    new public string ToString()
    {
    return ertek.ToString();
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Valami v = new Valami(5);
    GenerikusTipus<Valami> genTip = new GenerikusTipus<Valami>(v);
    Console.WriteLine(genTip.GetErtek().ToString());
    genTip.TorlunkHaTudja();
    Console.WriteLine(genTip.GetErtek().ToString());
    Console.ReadKey();
    }
    }
    }

    A "megoldásom":
    Az as operátor ugye csak referencia, ill. nullabe típusok esetén működik. Tehát akkor az adott típust ki kell tenni object-be(ami ugyebár referencia típus), ez már magában hordozza a "metaadatokat" is. Na most így már alkalmazhatónak kell lennie az object példányra az as operátornak. Viszont a végén az adat-ba be kell tenni a kapott értéket.

    if (adat is ITorol)
    {
    object o = adat;
    (o as ITorol).delete();
    adat = (T)o;
    }

    Ez érdekességnek jó, de "élesben" nem igazán használnám...

    Ha ezt a kódot(és a megoldást) valaki becsülettel megnézi, akkor egyértelműen látszik, hogy a metódusok 1 boxingolt típussal(másolattal) dolgoznak. Ezért van az, hogy az o objectet a törlés után vissza kell tenni az aktuális mezőbe. Az érték típusok csak az alapműveletek esetén(*/+-) nagyon gyorsak. metódushívás esetén nagyon lassú.

Új hozzászólás Aktív témák