2011-10-18 11 views
11

Czytałem dużo o finalizatorze i IDisposable w języku C#. Kiedy w końcu staję się jasny z powodu tego potwornego zamieszania nad finalizatorem i IDisposable, nagle, znikąd, pojawia się ta sprawa SafeHandle. Moja wiara znów jest całkowicie wstrząśnięta. Co mam użyć?C# use IDisposable lub SafeHandle?

+2

Używaj dla * co *, dokładnie? –

+0

Wykorzystaj do czego, dokładnie. Nie wiem, który powinienem użyć w jakiej sytuacji teraz, gdy są 2 takie pozornie podobne konstrukcje. –

+1

@HansPassant Podczas czytania postu MSDN o tym, jak zaimplementować IDisposable, Microsoft przedstawia dwie opcje, jak to zaimplementować. Jedna implementuje finalizator, a zalecana używa SafeHandle. Jest to rzeczywiście nieco mylące i wprowadzające w błąd, więc bardzo dobrze rozumiem pytanie OP. URL: http://msdn.microsoft.com/en-us/en-en/library/fs2xkftw%28v=vs.110%29.aspx Witryna sprawia, że ​​brzmi to bardzo ogólne, więc moja pierwsza próba uzyskania mojego Obiekty pióra odpowiednio rozmieszczone były również z SafeHandle, które nie było zbyt produktywne. – Tom

Odpowiedz

15

SafeHandle jest przydatny tylko w przypadku wywołań Win32 Interop. W Win32 większość rzeczy jest reprezentowana przez "uchwyty". Obejmuje to system Windows, Mutexy itp. Dlatego też .NET SafeHandle używa wzorca jednorazowego użytku, aby zapewnić właściwe zamknięcie sterownika Win32.

Więc jeśli używasz wywołań Win32 Interop i odzyskujesz uchwyty Win32, użyj SafeHandle. Dla twoich własnych obiektów trzymasz się IDisposable i finalizatora.

+0

Ale cały punkt [IDisposable] (https://msdn.microsoft.com/en-us/library/system.idisposable (v = vs.110) .aspx), to wydawanie * niezarządzanych * zasobów, nie jest to? "twoje własne obiekty" brzmi niejednoznacznie, ponieważ obiekt może reprezentować obiekt zarządzany * i * niezarządzany, a ponieważ programista może rozwijać zarówno kod zarządzany i niezarządzany, jak i wywoływać niezarządzany kod z zarządzanego kodu, twoja definicja "własnego" jest również rozmyte. –

+0

@ zespri - Jeśli decydujesz się na wdrożenie IDisposable, oznacza to, że utrzymujesz klasę/obiekt (to znaczy twój). Jeśli jest to obiekt z biblioteki innej firmy, nie można zaimplementować IDisposable (tzn. Nie jest to Twoja). Nie mówię o tym, co powinno zostać usunięte, ani nie będziesz implementował IDisposable w niezarządzanym kodzie. – CodeNaked

+0

Ale jeśli jest to obiekt z biblioteki innej firmy (zarządzanej), nie możesz zaimplementować 'SafeHandle'?Tylko dlatego, że i tak prawdopodobnie nie będziesz mieć żadnej bezpośredniej widoczności uchwytu? Przepraszam, nie jestem wojowniczy, tylko próbuję zrozumieć, co masz na myśli. –

5

Możesz/powinien używać SafeHandle dla dowolnego niezamanizowanego zasobu, który może być reprezentowany jako IntPtr, tzn. Win32 obsługuje, pamięć przydzielona przez niezarządzany kod i tak dalej. Kiedy SafeHandle nie jest odpowiedni, ale nadal musisz radzić sobie z niezarządzanymi źródłami, rozważ utworzenie własnej klasy przypominającej SafeHandle dziedziczącej po CriticalFinalizerObject.

We wszystkich innych przypadkach (tj. W zakresie zarządzania zasobami zarządzanymi) zaimplementuj IDisposable. W większości przypadków nie będziesz potrzebował finalizatora, większość zarządzanych zasobów będzie niedostępna po wywołaniu finalizatora, więc nie byłoby tam nic do zrobienia.

2

W większości przypadków moja rada byłaby udawaniem, że nie ma czegoś takiego jak finalizator, ale w 100% upewnia się, że wszelkie obiekty IDispozycyjne, które są tworzone, zostają zniszczone. Nawet jeśli finalizatory są napisane w 100% optymalnie, kod, który prawidłowo pozbywa się połowy swoich obiektów i pozwala finalizatorom obsługiwać drugą połowę, nie będzie tak dobry, jak kod, który poprawnie pozbywa się wszystkich obiektów i nie używa finalizatorów. Chociaż prawdą jest, że wpływ wykonawców, którzy nigdy nie działają, jest niezbyt straszny, finalizatorzy są trudni do napisania poprawnie, mogą spowodować, że Heisenbugs, jeśli ich kod lub kod, który je pochłonie, nie zostanie napisany idealnie. Ponadto, udana implementacja finalizatorów będzie często wymagać utworzenia jednej lub kilku Słabych Praw, których jedynym celem jest wsparcie finalizacji.

Być może zabezpieczenie przed sfinalizowaniem jest warte kosztów, ale koszt może być znaczny, a sieć bezpieczeństwa nie jest tak niezawodna, jak by się tego chciało.

Powiązane problemy