Vra

As die eerste plek 'n C ++ ontwikkelaar die afwesigheid van RAII (Bron verkryging inisialisering) in Java en NET het my altyd gepla. Die feit dat die onus van die skoonmaak van geskuif vanaf die klas skrywer om sy verbruikers (deur middel van try finally of NET se using konstruk ) lyk aansienlik minderwaardig te wees.

Ek sien waarom in Java daar is geen ondersteuning vir RAII sedert al die voorwerpe is geleë op die wal en die vullis versamelaar nie inherent nie ondersteun deterministiese vernietiging, maar in NET met die bekendstelling van waarde-tipes (struct) het ons die (oënskynlik) perfekte kandidaat vir RAII. 'N Waarde tipe dit is geskep op die stapel het 'n goed gedefinieerde omvang en C ++ destructor semantiek gebruik kan word. Maar die CLR nie toelaat dat 'n waarde-tipe om 'n destructor het.

My ewekansige soektogte gevind een argument dat indien 'n waarde-tipe is doos dit val onder die jurisdiksie van die vullis versamelaar en dus sy verwoesting word nie-deterministiese. Ek voel dat hierdie argument is nie sterk genoeg is, die voordele van RAII is groot genoeg om te sê dat 'n waarde-tipe met 'n destructor nie kan doos (of gebruik as 'n klas lid).

Om 'n lang storie kort my vraag is : is daar enige ander redes tipes waarde kan nie gebruik word om RAII stel NET? (Of dink jy my argument oor ooglopende voordele RAII se gebrekkig?)

Edit: Ek moes nie die vraag duidelik sedert die eerste vier antwoorde op die punt gemis het geformuleer. I weet oor Finalize en sy nie-deterministiese kenmerke, ek weet van die using konstruk en ek voel hierdie twee opsies is minderwaardig teenoor RAII. using is nog een ding die verbruiker van 'n klas moet onthou (hoeveel mense het vergeet om 'n StreamReader in 'n using blok sit?). My vraag is 'n filosofiese een oor die taal ontwerp, waarom is dit die manier waarop dit is en kan dit verbeter word?

Byvoorbeeld met 'n generiese deterministisch vernietig waarde-tipe kan ek maak die using en lock sleutelwoorde oorbodig (bereikbaar deur biblioteek klasse):

    public struct Disposer<T> where T : IDisposable
    {
        T val;
        public Disposer(T t) { val = t; }
        public T Value { get { return val; } }
        ~Disposer()  // Currently illegal 
        {
            if (val != default(T))
                val.Dispose();
        }
    }

Ek kan nie help nie, maar eindig met 'n propos aanhaling wat ek een keer gesien, maar kan tans nie vind sy oorsprong.

  

Jy kan my deterministiese vernietiging neem toe my koue dooie hand gaan uit van omvang. - Anon

Was dit nuttig?

Oplossing

'n beter titel sou wees "Hoekom is daar geen RAII in C # / VB". C ++ / CLI (Die evolusie van die aborsie wat Bestuurde C ++) het RAII in presies dieselfde sin as C ++. Dit gaan alles net sintaksis suiker vir dieselfde finalisering patroon wat die res van die CLI tale gebruik (Destructors in beheer voorwerpe vir C ++ / CLI is effektief finalisers), maar dit is daar.

Jy mag dalk graag http://blogs.msdn.com /hsutter/archive/2004/07/31/203137.aspx

Ander wenke

Uitstekende vraag en een wat my baie gepla. Dit wil voorkom asof die voordele van RAII baie verskillend beskou. In my ervaring met NET, die gebrek aan deterministiese (of ten minste betroubare) bron versameling is een van die groot nadele. Trouens, NET my 'n paar keer gedwing om hele argitektuur te gaan met onbeheerde hulpbronne wat in diens mag (maar dalk nie) vereis eksplisiete versamel. Wat natuurlik, is 'n groot nadeel, want dit maak die algehele argitektuur moeiliker en gelas aandag van die kliënt se weg van die meer sentrale aspekte.

Brian Harry het 'n mooi boodskap oor die rasionaal hier .

Hier is 'n uittreksel:

  

Wat van deterministiese finalisering en waarde tipes (structs)?

     

-------------- Ek het 'n baie vrae gesien oor structs met   destructors, ens Dit is die moeite werd   kommentaar te lewer. Daar is 'n verskeidenheid van   kwessies vir waarom sommige tale nie   het hulle.

     

(1) samestelling - Hulle het nie jy gee   deterministiese leeftyd in die algemeen   geval vir dieselfde soort samestelling   redes hierbo beskryf. Enige   nie-deterministiese klas met een   sou nie bel die destructor totdat dit   was in elk geval gefinaliseer deur die GC.

     

(2) 'n afskrif vervaardigerskampioenskap - Die een plek   waar dit sal baie mooi is in wees   stapel toegeken locals. Hulle sou wees   scoped aan die metode en al sou wees   groot. Ongelukkig, in orde te kry   hierdie om regtig te werk, moet jy ook   voeg kopie konstruktors en noem dit   elke keer as 'n geval is gekopieer.   Dit is een van die lelikste en die meeste   komplekse dinge oor C ++. Jy beland   kry kode uitvoering regoor die   plek waar jy dit nie verwag nie. Dit   veroorsaak trosse van taalprobleme.   Sommige taal ontwerpers gekies het om   bly weg van hierdie.

     

Kom ons sê ons geskep structs met   destructors maar bygevoeg 'n klomp van die   beperkings op hul gedrag te maak   sinvolle in die gesig van die kwessies   hierbo. Die beperkings sal wees   iets soos:

     

(1) Jy kan net verklaar hulle as plaaslike   veranderlikes.

     

(2) Jy kan hulle net slaag   deur-ref

     

(3) Jy kan hulle jou nie ken   kan slegs toegang velde en oproep   metodes op hulle.

     

(4) Jy kan nie boks   hulle.

     

(5) Probleme met behulp van hulle deur   Weerspieëling (laat bind), want dit   gewoonlik behels boks.

     

miskien meer,   maar dit is 'n goeie begin.

     

Wat gebruik sal hierdie dinge wees, sou   jy eintlik 'n lêer of 'n te skep   databasis konneksie klas wat kan   Slegs gebruik word as 'n plaaslike veranderlike? Ek   glo nie enigiemand regtig sou doen.   Wat jy in plaas sou doen is skep 'n   algemene doel verband en dan   skep 'n motor verwoes wrapper vir   gebruik as 'n scoped plaaslike veranderlike. Die   oproeper sal dan kies wat hulle   wou gebruik. Let op die oproeper het 'n   besluit en dit is nie heeltemal   vervat in die voorwerp self.   Gegewe dat jy iets kan gebruik   soos die voorstelle kom in 'n   paar artikels.

Die plaasvervanger vir RAII in NET is die gebruik van-patroon, wat werk amper net so goed as jy eers daaraan gewoond te raak.

Die naaste wat jy kry om dit is die baie beperkte stackalloc operateur.

Daar is 'n paar soortgelyke drade as jy soek vir hulle, maar basies wat dit kom daarop neer dat as jy wil RAII op NET 'n IDisposable tipe eenvoudig te implementeer en gebruik die "gebruik van" n verklaring aan deterministiese Beskikking kry. Op dié manier baie van dieselfde ideoms geïmplementeer kan word en gebruik word in net 'n bietjie meer langdradig wyse.

IMHO, die groot dinge wat VB.net en C # behoefte is:

  1. 'n "gebruik" verklaring vir velde, wat sou veroorsaak dat die samesteller na-kode te genereer om ontslae van al so gemerk velde. Die verstek gedrag moet wees vir die samesteller om 'n klas te implementeer IDisposable as dit nie gebeur nie, of voeg beskikking logika voor die aanvang van die belangrikste beskikking roetine vir enige van 'n aantal algemene IDisposal implementering patrone, of anders gebruik 'n kenmerk te bepaal dat die beskikking dinge moet gaan in 'n roetine met 'n spesifieke naam.
  2. 'n middel van deterministisch ontslae van voorwerpe waarvan die vervaardigerskampioenskap en / of in die veld initializers gooi 'n uitsondering, hetsy deur 'n verstek gedrag (die roeping van die metode verstek beskikking) of 'n persoonlike gedrag (uitroep van 'n metode met 'n spesifieke naam) .
  3. Vir vb.net, 'n outomaties gegenereerde metode om nul al WithEvent velde.

Al dié kan baie goed wees kludged in vb.net, en 'n bietjie minder goed in C #, maar die eerste-klas ondersteuning vir hulle sou beide tale te verbeter.

Jy kan 'n vorm van RAII doen in NET en Java behulp finaliseer () metodes. A Finaliseer () oorlading genoem voor die klas te word skoongemaak deur die GC en so kan gebruik word om skoon te maak van enige hulpbronne wat absoluut nie deur die klas gehou moet word (mutexes, voetstukke, lêer handvatsels, ens). Dit is nog nie deterministiese though.

Met NET jy kan 'n paar van dit te doen deterministisch met die IDisposable koppelvlak en die gebruik van die term, maar dit het wel beperkings (met behulp van konstrueer wanneer dit gebruik word benodig vir deterministiese gedrag, nog geen deterministiese geheue deallocation, nie outomaties gebruik in klasse, ens ).

En ja, ek voel daar is 'n plek vir RAII idees in NET en ander het daarin geslaag tale te voer, hoewel die presiese meganisme eindeloos kan gedebatteer word. Die enigste ander alternatief wat ek kon sien sou wees om 'n GC wat kan hanteer arbitrêre hulpbron opruim (nie net die geheue), maar dan kwessies het u bekend te stel wanneer gesê hulpbronne absoluut moet deterministisch vrygelaat word.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top