Jij zei dat het soms niet hoeft. Wanneer niet is niet duidelijk dan want je hebt alleen maar een interface op een class.
Jij ziet dit verschil liever niet, om op zich goede redenen, maar in de doelstellingen van .NET staat performance hoger dan encapsulatie. In de oplossing die jij beschrijft heeft ieder object een finalizer, dat zou gigantische impact op de performance hebben. Je zou niet meer kunnen zien welke objecten clean-up moeten doen, omdat ieder object een dispose methode heeft.
Nee, niet ieder object heeft een finalizer, alleen de classes die een unsafe resource referencen hebben een IDisposable implementatie en de GC roept dan de Dispose() routine aan wanneer het object outofscope gaat. Als je dat zelf al gedaan hebt, doet die dus niet veel meer. Veel simpeler. Overigens doe jij net alsof een finalizer hebben megatraag is, wat onzin is, het scheelt een paar cycles.
Je zou je wel kunnen afvragen waarom er een verschil is gemaakt tussen de finalizer en de dispose methode. Waarom niet gewoon de finalizer zelf aanroepen? Ik denk dat echter het verschil gemaakt is juist om aan te geven voor welke objecten dit wél nodig is. Als een object een finalizer heeft wil dat nog niet zeggen dat ie zo snel mogelijk moet worden opgeruimd.
Nou als dat de reden is dan is dat een behoorlijke domme. De complete FCL is opgezet met in het achterhoofd: create en de GC ruimt het wel op. Nu moet je dan ineens bij elke class de IDisposable interface implementatie gaan nakijken? Lijkt me een onzinnige eis, want je verzandt dan in het aloude pattern wat ook in C++ gebruikt wordt, nl. dat je al je pointers moet deleten die je new't. Sterker, met smart pointers heb je het MAKKELIJKER in C++ dan in .NET op die manier. Ergo: onzin: creeer de objects, en wanneer ze outofscope gaan ruimt de GC ze op. Bedien je wel van Close() wanneer je een open doet, en that's it.
[...]
Je geeft zelf het verschil al aan: na close() mag je het object wél hergebruiken, na dispose() niet.
Van wie mag ik dat niet? Zie je niet hoe fout die visie is die erachter zit... Ik roep een method aan op een object en daarna mag ik het object niet meer gebruiken, maar het is er nog wel...
Ik ben het met je eens dat dispose() in dit geval een beetje redundant is, maar het is geïntroduceerd om juist een stukje resource management generiek op te kunnen lossen.
Maar waarom moet ik me daarmee bezig houden? Ten eerste WEET ik helemaal niet of de class resources in zich heeft en OF dat een dispose call vereist (ik heb de source niet) en ten tweede heb ik de GC die het voor me regelt, waarom moet ik me bezig houden met resource cleaning? Kan ik beter C++ gaan programmeren met smart pointers en COM, want dat is EN sneller, EN makkelijker.
De naam Close() is niet voor iedere soort resource acceptabel, en ook niet iedere soort resource is her-openbaar. Daarom is de dispose() generiek genoeg gemaakt om voor iedere soort resource clean-up te kunnen dienen.
Je werkt met objects, niet met resources. Als je doet:
Treenode n = myTree.Nodes.Add(...);
moet je dan n.Dispose() aanroepen als je weer doet:
myTree.Nodes.Remove(n);
?
Indien JA, dan heeft .NET een serieus probleem.
.NET heeft precies hetzelfde probleem als iedere ander platform: als je niet weet hoe alles werkt dan kun je in gigantische problemen komen. Het IDisposable patroon is juist om te voorkomen dat de finalizer wordt aangeroepen, dus Microsoft spreekt zichzelf daar echt niet tegen. Jij vindt echter IDisposable een implementatie detail dat je liever niet gebruikt. Dat ziet Microsoft dus (terecht) wel anders.
Zucht, ik word hier wel een beetje moe van. Ten eerste wil ik helemaal niet bezig zijn met resource management, daarom gebruik ik een platform met een GC. Ten tweede WEET ik helemaal niets van resource management van objects die ik gebruik, ik heb de source niet. Ten derde HOEFT het ook niet, want .NET regelt het voor me.
Waarom een interface? Ooit over nagedacht? Wellicht omdat je dan in een .NET class / onderdeel generiek die handel kunt opruimen? De eis dat je alle methods moet nagaan die geimplementeerd worden in een class en dan daarvanaf moet leiden dat je een method MOET aanroepen voor resource management lijkt me het paard achter de wagen spannen.
[...]
Zit ik er naast dan? Als jij mij betrapt op een onwaarheid in dit verhaal hoor ik het graag.
Je verhaal over dit: zodra IDisposable is geimplementeerd moet je Dispose aanroepen, of iig: de implementatie zegt dat je beter Dispose kunt aanroepen want er zit kennelijk iets intern gereferenced en dat levert anders trage software op. Wat onzin is uiteraard.
[...]
Het stukje documentatie klopt inderdaad, en beschrijft bijna letterlijk wat ik vertelde. Er staat heel duidelijk dat de finalizer van een disposable als backup moet dienen, en dat de programmeur hier zelf voor moet zorgen.
Van de class die de unsafe resource referenced ja, dus niet jouw pakkie-an.
Dat is dus net even iets minder kort door de bocht als "Wanneer een object IDisposable implementeert dan zal de GC altijd Dispose() aanroepen". De bewoordingen die gebruikt worden in dit stukje (en ik ben er zeker van dat in een andere alinea van deze help-pagina dit expliciet verteld wordt) geven ook aan dat de dispose aanroepen via de finalizer een backup, als de programmeur "gefaald" heeft.
Gefaald? Wanneer? En welke programmeur? Die programmeur die een ADO.NET connection object gebruikt in een class en niet IDisposable implementeert? Of die programmeur die een class gebruikt die IDisposable implementeert?
BEIDE hoeven IDisposable helemaal niet te implementeren. Alleen als je ZELF een unsafe object referenced. En wanneer komt dat voor? Nauwelijks. Daarnaast heb je dus het gebruik van classes die unsafe resources schijnen te gebruiken (maar dat weet jij niet en ik ook niet en ik WIL het ook helemaal niet weten). Ik ga dan echt geen Dispose() lopen aanroepen op allerlei objects of erger: hele try/finally trees bouwen alleen om ieder object dat ik creeer ook te kunnen disposen. Dat zoekt die GC maar fijn uit!
Jij doet dat wel? En wat win je ermee? 10 cycles op je P4-3Ghz? Als het werkelijk zo nodig is dan is het beter vertoeven in de COM wereld met VC++. Smartpointer naar het object en hij gaat vanzelf out-of-scope en de smartpointer ruimt het wel op. Opgelost.
[...]
Je hebt de volgende regel die ik over opgeschreven heb ook gequote, heb je hem ook gelezen? Hier legde ik uit dat de dispose methode er meestal voor zal zorgen dat de finalizer niet zal worden gebruikt in de GC, als de dispose methode al eerder is aangeroepen. Je hebt dus ALLEEN last van de performance dip als de dispose() NIET wordt aangeroepen in de code.
En hoe groot is die dip denk je... jij merkt hem echt niet hoor. Is er wel een dip die je merkt dan is het Microsoft's schuld, ZIJ zijn verantwoordelijk voor de performance van de GC, niet de developer zelf.
[...]
Sorry hoor, maar nu begin je wel een beetje kinderachtig te doen. Jij weet ook vast wel dat er zoiets als een managed heap bestaat, en die kun je net zo goed in de poeier helpen. Dat "managed" moet je wel met een korreltje zout nemen. Ik zie ook niet hoe dit nu buiten de scope van het probleem ligt. Het probleem was performance, en de performance van een applicatie kan echt dramatisch slechter zijn als je simpelweg niet goed met je objecten om gaat.
Ik doe niet kinderachtig, ik gebruik MS' marketingpoep argumenten. Als .NET developer heb je geen rekening meer te houden met memory management. Nou, dat doe ik dan ook niet. Moet ik volgens jou dan ineens daar WEL rekening mee gaan houden? Wie lult er dan uit zn nek: jij of MS? Ja ik weet ook wel dat een array van tigduizend grote objects veel memory consumption oplevert, maar de 'heap' is niets anders dan een truukje om memory allocation wat sneller te laten verlopen, iets wat hoort bij de CLR en internals niet bij de developer en zn code. Want, als het zo belangrijk is, waarom kan ik dan geen heap alloc doen of de heap grootte managen?
Dat is dus bad practice. De finalizer is een vangnet, en hier moet niet expliciet gesteund op worden door de programmeur. Dat jij vindt dat het niet zo hoeven heeft de rest van de .NET wereld eerlijk gezegd weinig aan denk ik.
Nee, JIJ vindt dat bad practise. De keypoints voor .NET zijn heel duidelijk en daar hoort eigen gepruts met memory management en vrijgeven van resources NIET bij, dat zou juist tot het verleden behoren. Overigens, wat ik vind heeft de .NET wereld wel degelijk wat aan, het lullige is dat er meer mensen naar wat ik vind luisteren dan jij denkt. Voorbeeld waarom ik gelijk heb en jij niet? Zoek de regel eens op in de .NET documentatie waarin MS expliciet zegt dat wanneer een class een public Dispose method heeft, deze ook moet worden aangeroepen?
Ik begrijp je mierenneuken ook niet echt. Is me al vaker opgevallen, maar je wilt werkelijk IEDERE regel die ik zeg en waar volgens jou iets in staat wat niet klopt rechtzetten. De DataSet bv heeft ook een Dispose() method. Ik moet het eerste stukje code nog zien waar de Dispose method van de dataset wordt aangeroepen. Jij roept bij elke dataset de Dispose() aan? Indien NEE: waarom niet? Volgens jouw woorden MOET je die aanroepen want het is een public Dispose() method.
Ik weet ook niet direct waarom een dispose() niet volgens OO zou zijn, en een close() wel.
Een Close() maakt een actie-sequence compleet. Ik kan daarna het object gewoon weer gebruiken of beter: verder gebruiken. Dispose() is ook een method net als ieder ander. Echter wanneer ik Dispose() aanroep is mn object in een toestand dat ik het niet meer kan (of jouw woorden: 'mag') gebruiken.
Dat dispose is dus een vrij rare method, want het helpt het object intern om zeep terwijl het object er nog wel gewoon is.
Een object is een eenheid van verantwoordelijkheid, en als in het contract van het object staat "roep de dispose zo snel mogelijk aan nadat je klaar met me bent, anders wordt het traag" dan zie ik niet zo goed hoe dit nu anti-OO is. Vervelend dat je er op moet letten, ben ik absoluut met je eens, maar dit is gewoon de realiteit.
Nee dat is de realiteit niet. Het is NIET traag, en er bestaan ook niet contracten als 'roep dit aan want anders!!!!'. Interface contracts gaan niet zover, zeker niet met bv C#.
[...]
Tja als je het zo bekijkt. Dat zou dus inhouden dat naast een finalizer en een dispose methode er nog een derde close() methode nodig is die alles opruimt. En is dat wel zo? Als een connectie zichzelf na een close() nog kan openen, heeft ie dan niet stiekem nog wat resources vast om dit te kunnen? Ik weet het niet, met dispose zit je altijd goed. De resources waar het bij dispose() om gaat zijn wél schaars, anders hoef je ze niet zo vroeg vrij te geven. Of stel jij het aantal connecties in je pool op oneindig in? Dan heb je niet zo veel meer aan je pool.
Huh? Weet je wel hoe een pool werkt?

Ik weet helemaal niet welke resources een class in zich heeft en of die schaars zijn (lijkt me naar, schaarse resources. Nog een paar threads en je systeem slaat vast) en of die vrijgegeven MOETEN worden. Ik roep alleen Open aan en dan verwacht ik dat iets opent en bij Close() sluit het weer. Wat er verder onder water gebeurt zoekt die class maar fijn zelf uit. Ga jij jezelf vermoeien met hoe dat dan allemaal intern gebeurt en wat 10 cycles bespaart? Jij roept ipv Close() gewoon Dispose() aan op een ado.net connection, omdat Dispose() onder water close() aanroept?
[...]
Heel simpel: als ie disposable is, dan moet je er altijd voor zorgen dat de dispose() wordt aangeroepen.
Goed, dus jij roept Dispose() aan op dataset, datatable, dataview? En op al je controls natuurlijk wanneer je een form sluit! Want een grid bv die een dataset bind bind met een dataview. Dus je moet dan die dataview OOK disposen wanneer de grid out of scope gaat. Wat een overbodige code. Het is nl. nergens voor nodig.
Jij roept "maar 2 gig aan handles", nou als een applicatie dat ook daadwerkelijk alloceert dan merk je wel degelijk dat dat niet zo handig is. Je hoeft niet precies te weten wat er allemaal onder water gebeurt, je hoeft alleen te weten dat je netjes disposed, en dan zal het allemaal in de meeste gevallen wel loslopen.
Wat is dat nou voor redenatie.. "roep maar aan, baat het niet dan schaadt het ook niet, en het helpt... meestal". Als mn applicatie uit zn resources loopt (en dat lijkt me heel sterk, met 2gb aan handles per process) dan heb ik een probleem. Ik kan dan disposen wat ik wil, maar dat boeit niet, ik zal toch aan die limiet raken bij iets meer load bijvoorbeeld.
Als je bv gewoon Close() aanroept op streams, op Connections e.d. dan heb je het al opgelost. Dat dispose aanroepen op treenodes bv is zo ongelovelijke onzin. Een form heeft wellicht honderden HWND's en per control (en subcontrol) een HDC... worden die wel allemaal op tijd gedisposed, anders krijg je heap trashing!. Nee dus. .NET is juist ervoor om je NIET meer zorgen te maken over dat soort shit. Jij mag je hoofd daar middagen over breken hoor, maar je hebt alleen jezelf er maar mee.
[...]
Tja event handlers zijn natuurlijk weer een totaal andere discussie. En als jij het zo vervelend vind om dispose te doen dat je alles vertraagt door het de finalizers op te laten knappen, be my guest.
HOEveel vertraagt het dan? Weet je dat uberhaupt wel? En als ik geen unmanaged resources reference (indirect) door die objects, of het dan uberhaupt wel traag is? (nee)
Jij bent o zo bang voor dangling resources. Het zijn juist dangling eventhandlers die voor referenced objects zorgen die niet meer gefreeed worden en DUS voor memory leaks en dus tragere performance. Niet die dispose calls.
Als je maar even een dikke disclaimer bij zet:
Dit is omdat EfBe dit mooier vindt, maar is géén practice die Microsoft aanbeveelt en
Het is géén onzin als je toch zelf de dispose aanroept, want dat is wel sneller..

Dit is wel een openbaar forum, dus ik vind dat je de verantwoordelijkheid hebt om dingen te vertellen zoals ze zijn, niet zoals je ze graag zou willen hebben.
Zeg piet snot, jij vertelt mij echt niet wat ik moet en niet moet, dus beetje dimmen.

Ik vertel hoe het is, jij maakt mensen bang met prietpraatjes over traagheid bij het niet doen van bepaalde dingen. MS beveelt helemaal NIETS aan, nergens staat dat je Dispose moet aanroepen a.s.a.p. en wanneer je kunt en bij ieder object die Dispose implementeert.
Maar ik heb nu wel genoeg tijd verknoeid aan deze onzin discussie.