Hvorfor er det ingen RAII i .NET?

stemmer
62

Å være først og fremst en C ++ utvikler fravær av RAII (Resource Oppkjøpet er initialisering) i Java og .NET har alltid plaget meg. Det faktum at den tyngende for å rydde opp er flyttet fra klassen forfatter til sin forbruker (ved hjelp av try finallyeller .NET sin usingkonstruksjon ) synes å være betydelig dårligere.

Jeg ser hvorfor i Java er det ingen støtte for RAII siden alle objekter er plassert på haugen og søppelinnsamler iboende tillater ikke determinis ødeleggelse, men i .NET med innføringen av verdityper ( struct) vi har (tilsynelatende) perfekt kandidat for RAII. En verdi type som er opprettet på stabelen har en godt definert omfang og C ++ destructor semantikk kan benyttes. Men CLR tillater ikke en verdi-type til å ha en destructor.

Mine tilfeldig søk fant man argument at hvis en verdi type er innrammet det faller inn under jurisdiksjon av søppel samler og derfor dens ødeleggelse blir ikke-deterministisk. Jeg føler at dette argumentet ikke er sterk nok, fordelene ved RAII er store nok til å si at en verdi-type med en destructor ikke kan eske (eller brukes som et gruppemedlem).

For å gjøre en lang historie kort spørsmålet mitt er : er det noen andre grunner verdityper kan ikke brukes for å introdusere RAII til .NET? (eller tror du mitt argument om RAII åpenbare fordelene er feil?)

Edit: Jeg må ikke ha formulert spørsmålet klart siden de fire første svarene har gått glipp av poenget. Jeg vet om Finalizeog de ikke-deterministiske egenskaper, jeg vet om usingkonstruere og jeg føler disse to alternativene er dårligere enn RAII. usinger en ting forbrukeren av en klasse må huske (hvor mange som glemte å sette en StreamReaderi en usingblokk?). Mitt spørsmål er en filosofisk en om språket design, hvorfor er det slik det er, og det kan bli bedre?

For eksempel med en generisk deterødeleggverditype kan jeg gjøre usingog locksøkeord redundante (oppnåelig ved bibliotek klasser):

    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();
        }
    }

Jeg kan ikke hjelpe, men ender med et apropos sitat som jeg så, men kan foreløpig ikke finne sin opprinnelse.

Du kan ta min deterministisk destruksjon når mitt kalde døde hånden går ut av omfanget. - Anon

Publisert på 06/10/2008 klokken 09:25
kilden bruker
På andre språk...                            


7 svar

stemmer
15

En bedre tittel ville være "Hvorfor er det ingen RAII i C # / VB". C ++ / CLI (Utviklingen av abort som ble Managed C ++) har RAII på nøyaktig samme måte som C ++. Alt er bare syntaks sukker for samme sluttbehandling mønster som resten av CLI språk bruker (destructors i administrerte objekter for C ++ / CLI er effektivt finalisers), men det er der.

Kanskje du har lyst http://blogs.msdn.com/hsutter/archive/2004/07/31/203137.aspx

Svarte 06/10/2008 kl. 10:48
kilden bruker

stemmer
13

Utmerket spørsmål og en som har plaget meg sterkt. Det ser ut til at fordelene ved RAII oppfattes svært forskjellig. I min erfaring med .NET, mangel på determinis (eller i det minste pålitelig) ressurs samling er en av de store ulemper. Faktisk har .NET tvang meg flere ganger for å ansette hele arkitekturer å håndtere ikke-administrerte ressurser som kan (men kanskje ikke) krever eksplisitt innsamling. Som selvfølgelig er en stor ulempe, fordi det gjør det overordnede arkitekturen vanskeligere og styrer kundens oppmerksomhet bort fra de mer sentrale aspekter.

Svarte 06/10/2008 kl. 09:44
kilden bruker

stemmer
12

Brian Harry har et fint innlegg om begrunnelser her .

Her er et utdrag:

Hva om determinisAvslutnings og verdityper (structs)?

-------------- Jeg har sett en rekke spørsmål om structs har destructors, etc. Dette er verdt kommentar. Det finnes en rekke problemer for hvorfor noen språk ikke har dem.

(1) sammensetning - De ikke gi deg deterministisk liv i det generelle tilfellet for de samme slags grunner sammensetning beskrevet ovenfor. Enhver ikke-deterministisk klasse som inneholder en vil ikke kalle destructor før det ble ferdigstilt av GC likevel.

(2) Kopi konstruktører - Ett sted der det ville virkelig være fint er i stabelen tildelt lokalbefolkningen. De ville bli omfangs til metoden og alle ville være flott. Dessverre, for å få dette til å virkelig fungere, må du også legge kopi konstruktører og kaller dem hver gang en forekomst er kopiert. Dette er en av de styggeste og mest komplekse ting om C ++. Du ender opp med å få kode utfører over alt hvor du ikke forventer det. Det fører bunter av språkproblemer. Noen språk designere har valgt å holde seg borte fra dette.

La oss si at vi skapte structs med destructors men lagt til en haug med restriksjoner for å gjøre deres atferd fornuftig i ansiktet av spørsmålene ovenfor. Restriksjonene vil være noe sånt som:

(1) Du kan bare erklære dem som lokale variabler.

(2) Du kan bare sende dem av-ref

(3) Du kan ikke tildele dem, du kan bare få tilgang felt og kalle metoder på dem.

(4) Du kan ikke boksen dem.

(5) Problemer med å bruke dem gjennom refleksjon (sen binding) fordi det vanligvis innebærer boksing.

kanskje mer, men det er en god start.

Hvilken nytte ville dette skje? Vil du faktisk lage en fil eller en databasetilkobling klasse som bare kan brukes som en lokal variabel? Jeg tror ikke noen egentlig ville. Hva ville du gjøre i stedet er å lage en generell tilkobling, og deretter opprette en automatisk destruert wrapper for bruk som en omfangs lokal variabel. Den som ringer vil da velge hva de ønsket å bruke. Legg merke til den som ringer har gjort en beslutning, og det er ikke helt innkapslet i selve objektet. Gitt at du kan bruke noe sånt som forslagene kommer opp i et par seksjoner.

Erstatningen for RAII i NET er å bruke-mønster, som fungerer nesten like bra når du blir vant til det.

Svarte 06/10/2008 kl. 09:57
kilden bruker

stemmer
1

IMHO, de store tingene som VB.net og C # behov er:

  1. en "hjelp" erklæring for felt, noe som ville føre til at kompilatoren å generere kode for å kvitte seg med alle felt og dermed merket. Standard virkemåte skal være for kompilatoren å lage en klasse implementerer IDisposable hvis den ikke gjør det, eller sett disposisjon logikk før starten av hoved disposisjon rutine for noen av en rekke felles IDisposal implementeringsmønstre, eller andre bruke et attributt for å angi at disponering ting skal gå i en rutine med et bestemt navn.
  2. et middel for deter avhending av gjenstander som har konstruktører og / eller felt initializers kaste et unntak, enten ved en standard oppførsel (ringer standardavhendingsmetode) eller en tilpasset oppførsel (kalle en metode med et bestemt navn).
  3. For vb.net, til en automatisk generert metode nulle ut alle WithEvent felt.

Alle disse kan kludged ganske bra i vb.net, og noe mindre bra i C #, men førsteklasses støtte for dem ville forbedre begge språk.

Svarte 14/12/2010 kl. 04:16
kilden bruker

stemmer
1

Det er noen lignende tråder hvis du søker etter dem, men i utgangspunktet hva det koker ned til er at hvis du ønsker å RAII på .NET bare gjennomføre en IDisposable type og bruke "hjelp" statement å få determinis Deponering. På den måten mange av de samme ideoms kan implementeres og brukes i bare en litt mer ordrike måte.

Svarte 06/10/2008 kl. 09:32
kilden bruker

stemmer
1

Det nærmeste du kommer til det er svært begrenset stackalloc operatør.

Svarte 06/10/2008 kl. 09:27
kilden bruker

stemmer
-3

Du kan gjøre en form for RAII i .net og Java ved hjelp av sluttføre () metoder. En sluttføre () overbelastning kalles før klassen er ryddet av GC og så kan brukes til å rydde opp i eventuelle ressurser som absolutt ikke skal oppbevares av klassen (mutexes, stikkontakter, fil håndtak, etc). Det er fortsatt ikke deterministisk skjønt.

Med NET kan du gjøre noe av denne deterministisk med IDisposable grensesnittet og bruke søkeord, men dette har begrensninger (ved hjelp konstruere når det brukes nødvendig for deterministisk oppførsel, fortsatt ingen deterministisk minne fradeling, ikke automatisk brukes i klasser, etc).

Og ja, jeg føler det er et sted for RAII ideer til å bli innført i .NET og andre administrerte språk, selv om den eksakte mekanismen kan bli debattert uendelige. Den eneste andre alternativet jeg kunne se ville være å innføre en GC som kunne håndtere vilkårlig ressurs opprydding (ikke bare minne), men da har du problemer når sa ressurser absolutt må bli utgitt deterministisk.

Svarte 06/10/2008 kl. 09:31
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more