Minua pyydetään toteuttamaan IDisposable kohteille, jotka ovat 100-prosenttisesti hallinnoituja resursseja, joissa ei ole virtoja eikä suuria resursseja.
Ymmärrän suurten resurssien ja hallinnoimattomien resurssien asianmukaisen hävittämisen tärkeyden, mutta entä yhtälön toinen puoli?
Objektille, jolle ei ole hyötyä IDisposable (pienet, täysin hallitut objektit) toteuttamisesta , mitä negatiivisia vaikutuksia GC.SuppressFinalizella voi olla, jos sellaisia on?
Kommentit
Vastaa
Kohteen GC.SuppressFinalize
ainoa tavoite on:
estää viimeistelijää vapauttamasta hallitsemattomia resursseja, jotka ovat jo vapautuneet IDisposable.Dispose-toteutuksesta.
Kun olet hävittänyt objektin, sinun on todellakin kutsuttava vastaus kysymykseen GC.SuppressFinalize(this);
, kuten näkyy. ” Milloin minun pitäisi käyttää GC.SuppressFinalize ()? ”. Koodianalyysi ” CA1816 -sääntö on myös hyödyllinen.
Nyt IDisposable
käyttöönotto esineet, joilla ei ole hallitsemattomia resursseja, näyttää melko oudolta ja kyseenalaiselta. Koska ainoa syy, jonka henkilö antoi sinulle, oli: ”Se on juuri niin kuin olemme aina tehneet, niin teet sen myös” sen sijaan, että annat profilointi- / vertailutiedot, jotka osoittavat, että lisäämällä IDisposable
parantaa jotain erityistapauksessa, ei ole mitään todellisia syitä sen tekemiseen.
aiheuttaako se suorituskykyongelmia? Vaikea sanoa: se riippuu yksittäisestä tapauksesta.
tietysti. Jos ei oteta huomioon sitä, että IDisposable
on tuskallinen toteuttaa, jos tätä käytäntöä käytetään liikaa, koodista tulee lukukelvoton ja mahdoton ylläpitää:
public int ComputePrice(Rebate rebate) { using (var currentCurrency = this.User.FindCurrency()) { using (var priceWithoutRebate = this.GetPurePrice()) { using (var canApplyRebate = rebate.CanApplyTo(this)) { if (!canApplyRebate) { return priceWithoutRebate; } using (var priceWithRebate = priceWithoutRebate.Apply(rebate)) { return priceWithRebate; } } } } }
Kommentit
- No, uskon, että tarina on, että heillä oli kauan sitten yhteys / suoratoista vuotavia ongelmia, luultavasti vuotaneen yhteyden / komennon ADO.NET-koodin takia, mikä aiheutti valtavia resurssivuotoja. He tiesivät, että IDisposable-sovelluksen toteuttaminen kaikessa ratkaisi ongelman, joten he tekivät, ja se toimi. Ja niin nyt he j On pantava se täytäntöön useimmissa kohteissa.
- @AndrewHoffman: se näyttää olevan uskottava selitys. Mutta se ei silti ' perustele nykyistä käytäntöä.
Vastaa
Sinun ei tarvitse käyttää painavaa (”tuskallista”) Hävitä + viimeistelijä -kuviota IDisposable-luokassa, jos luokka on sinetöity, eikä luokassa ole hallitsemattomia resursseja.
Tässä tilanteessa voit käyttää Hävitä + viimeistelijä -mallin osajoukkoa, jolla on vain julkinen Dispose()
, hänellä ei ole viimeistelijää, ja luokka on sinetöity.
Luokan sinetöinnin syy on välttää ongelmat ”Mitä jos lapsiluokalla on hallitsematon resurssi?” ja ”Entä jos lapsiluokalla on tulevaisuudessa hallitsemattomia resursseja?”
Joe Duffy, entinen Microsoft, on laajan (yli 30 sivua käsittelevän) artikkelin, jossa kerrotaan, miten ja kaikki permutaatio-osajoukototeutukset.
Artikkelin kirjoittajia ovat Herb Sutter, Brian Grunkemeyer, Jeff Richter ja muut C # -valaisimet. Artikkeli on paljon syvällisempi kuin mitä MSDN: ssä esitetään.
Valitettavasti, Joe Duffyn uusi blogimoottori ei ole tehnyt hyvää työtä säilyttääkseen alkuperäisen artikkelin vuodelta 2005, joten se näyttää hiukan mungerilta. Tässä on linkki: http://joeduffyblog.com/2005/04/08/dg-update-dispose-finalization-and-resource-management/
Toivon, että voisin liittää MS-Word-dokumenttini, jossa on koko Joe Duffyn artikkeli, paljon paremmin muoto. 🙁
IDisposable
lisääminen parantaa tässä tapauksessa muistin jalanjälkeä?IDisposable
kirjoittamatta tuhoajaa / viimeistelijää. En tiedä ' en tiedä, tarkoittiko henkilö, joka pyysi sinua toteuttamaanIDisposable
, myös sinun pitäisi tehdä tuhoaja. Tietysti, jos luokassa ei ole hävittäjää,GC.SuppressFinalize
-kohdassa ei ole mitään järkeä. Jos luokassa on tuhoaja, muista sanoaGC.SuppressFinalize(this)
, kun menetelmäDispose
on suoritettu. Muuten instanssia ei kerätä roskiin helposti, se jonotetaan viimeistelyjonoon ja se kerätään vain 2. sukupolven keräykseen.