Jag blir ombedd att implementera IDisposable på objekt som är 100% hanterade resurser, som inte innehåller några strömmar och inga stora resurser.

Jag förstår vikten av att bortskaffa stora resurser och ohanterade resurser korrekt, men hur är det med den andra sidan av ekvationen?

För ett objekt som inte gynnas av att implementera IDisposable (små fullt hanterade objekt) , vilken negativ inverkan kan GC.SuppressFinalize ha, om någon?

Kommentarer

  • Ser ut som för tidig optimering. Är du i stånd att be personen som bad dig göra att resultaten han fick av profilering och benchmarking som visar att lägga till IDisposable i detta fall förbättrar minnesavtrycket?
  • @MainMa Nej men det hindrade mig inte från '. Resultatet blev ett 5-minuters svar av " det är precis som vi ' alltid har gjort det, du gör det också ".
  • Tja, det är möjligt att implementera IDisposable utan att skriva en destruktor / finalizer. Jag vet inte ' om personen som bad dig implementera IDisposable menade att du också skulle göra en destruktör. Självklart, om klassen inte har någon destruktör, är det ingen mening i GC.SuppressFinalize. Om klassen har en förstörare, se till att säga GC.SuppressFinalize(this) när din Dispose -metoden har körts. Annars kommer förekomsten inte att samlas in skräp lätt, den kommer att köas i en finalizer-kö och samlas bara i en generation-2-insamling.
  • @JeppeStigNielsen Frågan säger att objekten hanterar helt hanterade resurser, så ' behöver inte ha en finaliserare. Om en är där vet vi att den ' är fel.

Svar

Det enda målet för GC.SuppressFinalize är:

för att förhindra att slutbehandlaren släpper ut ohanterade resurser som har redan befriats av IDisposable.Dispose implementering.

Källa: MSDN

När du väl har bortskaffat objektet bör du verkligen kalla GC.SuppressFinalize(this);, som visas i ett svar på frågan ” När ska jag använda GC.SuppressFinalize ()? ”. Kodanalys ” CA1816 -regeln är också användbar.

Nu implementeras IDisposable på objekt som inte har ohanterade resurser ser ganska konstiga och tvivelaktiga ut. Eftersom den enda anledningen som personen gav dig var: ”det är precis som vi alltid har gjort det, du gör det också”, istället för att tillhandahålla profilerings- / benchmarkingdata som visar att lägga till IDisposable kommer att förbättra något i ett specifikt fall, det finns inga faktiska skäl att göra det.

Skulle det orsaka prestandaproblem? Svårt att säga: det beror på specifikt fall.

Skulle det det orsakar några andra problem? Naturligtvis. Om man inte räknar med att IDisposable är smärtsamt att genomföra, om denna metod används för mycket blir koden oläslig och omöjlig att underhålla:

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

Kommentarer

  • Jag tror att historien är att för länge sedan hade de en viss koppling / problem med strömläckage, förmodligen på grund av läckande anslutning / kommando ADO.NET-kod, och detta orsakade massiva resursläckor. De visste att implementering av IDisposable på allt skulle lösa problemet, så de gjorde det och det fungerade. Och så nu gjorde de måste bara implementera det på de flesta föremål.
  • @AndrewHoffman: det verkar som en rimlig förklaring. Men det motiverar fortfarande inte ' t nuvarande praxis.

Svar

Du behöver inte använda det tunga (”smärtsamma”) Dispose + Finalizer-mönstret på en IDisposable-klass, om klassen är förseglad och klassen har inga ohanterade resurser.

I den situationen kan du använda en delmängd av Dispose + Finalizer-mönstret, som bara har offentligt Dispose(), har ingen finaliserare, och klassen är förseglad.

Anledningen till att försegla klassen är att undvika problemen med ”Vad händer om en barnklass har ohanterade resurser?” och ”Vad händer om en barnklass i framtiden kommer att ha ohanterade resurser?”

Joe Duffy, tidigare Microsoft, har en lång artikel (30+ sidor) som diskuterar hur man korrekt implementerar IDisposable och alla permutationsimplementeringsimplementeringar.

Bidragsgivare till artikeln inkluderar Herb Sutter, Brian Grunkemeyer, Jeff Richter och andra C # -armaturer. Artikeln är mycket mer djupgående än vad som presenteras på MSDN.

Tyvärr, Joe Duffys nya bloggmotor har inte gjort ett bra jobb med att bevara den ursprungliga artikeln från 2005, så den ser lite ut. Här är länken: / div> http://joeduffyblog.com/2005/04/08/dg-update-dispose-finalization-and-resource-management/

Jag önskar att jag kunde bifoga mitt MS-Word-dokument som har hela Joe Duffys artikel i en mycket bättre formatera. 🙁

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *