Interfejs IDisposable w języku C#
IDisposable - zwalnianie niezarządzanych zasobów
Głównym zastosowaniem interfejsu
IDisposable jest
zwalnianie niezarządzanych zasobów.
Niezarządzane zasoby są to elementy takie jak np.
pliki, strumienie i uchwyty do okien przechowywane przez obiekt. Aby zwolnić zasoby wywołujemy metodę
Dispose(). W przypadku użycia
Entity Frameworka (EF) zalecane jest używanie metody
Dispose() dla
contextu, zależy nam, aby zasoby były używane jak najkrótszy czas. Każde połączenie z bazą danych po zakończonym odczycie staje się bezużyteczne, ponieważ przy kolejny zapytaniu jest tworzone osobne połączenie z bazą, dlatego metoda Dispose pozwala na kontrolowane zwolnienie zasobów po prawidłowym odczycie danych. Podobnie wygląda sytuacja w przypadku odczytu plików czy połączenia z Internetem.
W przypadku użycia destruktora i
Garbage Collectora nie mamy wpływu na długość istnienia obiektu, ponieważ obiekty są trzymane jak najdłużej w celu ich ponownego użycia i są kasowane dopiero w momencie braku zasobów. Przyjęta została zasada, że każda klasa która działa na zewnętrznych zasobach oraz musi te zasoby zwalniać powinna dziedziczyć po interfejsie
IDisposable. W przypadku korzystania z kontenera
Inversion of Control (IoC zostanie dokładniej opisane w późniejszej części pracy w rozdziale wzorce projektowe) nie ma potrzeby korzystania z metody
Dispose(), ponieważ dla każdego typu obiektu deklarujemy jego cykl życia. Przykładowo dla połączenia z bazą danych jest to
PerWebRequest, czyli za każdym razem jest tworzony nowy obiekt a kontener
IoC automatycznie wywoła metodę
Dispose() po zakończonym odczycie danych.
Przykładowy kod prawidłowego użycia Dispose():
public class MojaKlasa:IDisposable
{
private bool IsDisposed=false;
public void Dispose()
{
Dispose(true);
GC.SupressFinalize(this);
}
protected void Dispose(bool Diposing)
{
if(!IsDisposed) {
if(Disposing)
{ // zwalniaj zasoby zarządzalne }
// zwalniaj zasoby niezarządzalne
}
IsDisposed=true;
}
~MojaKlasa()
{
Dispose(false);
}
}
Taka implementacja metody
Dispose() gwarantuje nam, że zasoby niezarządzalne zostaną wyczyszczone bez względu na to czy obiekt będzie automatycznie czyszczony przez
Garbage Collectora czy poprzez metodę
Dispose() wywołaną przez użytkownika. Dzieje się tak dzięki implementacji destruktora. Gdy użytkownik chce zwolnić obiekt informujemy
Garbage Collector że przejmujemy odpowiedzialność za obiekt przy pomocy metody
SupressFinalize(). Dzięki temu destruktor nie zostaje wywołany a my używamy metody
Dispose() z parametrem bool, który zabezpiecza przed podwójnym wykonaniem tej samej operacji. W przypadku gdy
Garbage Collector będzie chciał zwolnić zasoby jako pierwszy, zostaje wywołany destruktor wywołujący metodę
Dispose() na zasobach niezarządzalnych.
Więcej informacji na temat interfejsu IDisposable:
http://msdn.microsoft.com/pl-pl/library/system.idisposable.aspx
Komentarze facebook (polub nasz profil na FB aby je zobaczyć):