Zarówno DataSet, jak i DataTable implementują IDisposable, więc zgodnie z tradycyjnymi najlepszymi praktykami powinienem wywołać ich metody Dispose ().
Jednak z tego, co przeczytałem do tej pory, DataSet i DataTable nie mają w rzeczywistości żadnych niezarządzanych zasobów, więc Dispose () tak naprawdę niewiele robi.
Ponadto nie mogę po prostu użyć, using(DataSet myDataSet...)
ponieważ DataSet ma kolekcję DataTables.
Tak więc, aby być bezpiecznym, musiałbym iterować przez myDataSet.Tables, pozbyć się każdego z DataTables, a następnie pozbyć się DataSet.
Czy warto zatem wywoływać funkcję Dispose () na wszystkich moich DataSets i DataTables?
Uzupełnienie:
Dla tych z Was, którzy uważają, że DataSet powinien zostać usunięty: Zasadniczo wzorzec usuwania jest używany using
lub try..finally
, ponieważ chcesz zagwarantować, że zostanie wywołane Dispose ().
Jednak staje się to naprawdę brzydkie jak na kolekcję. Na przykład, co robisz, jeśli jedno z wywołań funkcji Dispose () zgłosiło wyjątek? Czy połykasz go (co jest „złe”), abyś mógł dalej pozbywać się następnego elementu?
Czy sugerujesz, żebym po prostu wywołał funkcję myDataSet.Dispose () i zapomniałeś o usuwaniu DataTables w myDataSet.Tables?
Odpowiedzi:
Oto kilka dyskusji wyjaśniających, dlaczego Dispose nie jest konieczne dla DataSet.
Pozbyć się czy nie wyrzucić? :
Czy należy wywoływać Dispose na obiektach DataTable i DataSet? zawiera wyjaśnienia MVP:
Zrozumienie metody Dispose i zestawów danych? ma komentarz Autorytetu Scott Allen:
Tak więc istnieje konsensus, że obecnie nie ma dobrego powodu, aby wywoływać Dispose on DataSet.
źródło
using
bloku, zależy od Ciebie.Aktualizacja (1 grudnia 2009 r.):
Chciałbym zmienić tę odpowiedź i przyznać, że pierwotna odpowiedź była błędna.
Oryginalna analiza ma zastosowanie do obiektów wymagających finalizacji - a argument, że praktyki nie powinny być akceptowane na powierzchni bez dokładnego i dogłębnego zrozumienia, nadal obowiązuje.
Okazuje się jednak, że DataSets, DataViews, DataTables blokują finalizację w swoich konstruktorach - dlatego wywołanie na nich Dispose () jawnie nic nie robi.
Przypuszczalnie dzieje się tak, ponieważ nie mają niezarządzanych zasobów; więc pomimo faktu, że MarshalByValueComponent uwzględnia rezerwy na niezarządzane zasoby, te konkretne wdrożenia nie mają takiej potrzeby i dlatego mogą zrezygnować z finalizacji.
(Autorzy .NET zadbają o to, aby finalizacja tego typu typów, które zwykle zajmują najwięcej pamięci, świadczy o znaczeniu tej praktyki w ogóle dla typów finalizowanych).
Niezależnie od tego, że szczegóły te są nadal niedokumentowane, odkąd system .NET Framework (prawie 8 lat temu) jest dość zaskakujący (że zasadniczo pozostawiasz swoje własne urządzenia do przesiewania przez sprzeczne, niejednoznaczne materiały, aby połączyć elementy razem jest czasami frustrujący, ale zapewnia pełniejsze zrozumienie ram, na których codziennie polegamy).
Po wielu lekturach, oto moje zrozumienie:
Jeśli obiekt wymaga finalizacji, może zajmować pamięć dłużej niż jest to konieczne - oto dlaczego: a) Każdy typ, który definiuje destruktor (lub dziedziczy po typie, który definiuje destruktor) jest uznawany za finalizowalny; b) Przy alokacji (przed uruchomieniem konstruktora) wskaźnik umieszczany jest w kolejce finalizacji; c) Obiekt finalizowalny zwykle wymaga Wyłączenia finalizacji nieco wyłącza nagłówek obiektu, wskazując środowisku wykonawczemu, że nie musi być wywoływany jego finalizator (nie musi przenosić kolejki FReachable); Pozostaje w kolejce finalizacji (i nadal jest zgłaszany przez! FinalizeQueue w SOS) 2 kolekcji. odzyskania (zamiast standardowej 1); d) Pomijanie finalizacji nie usuwa obiektu z kolejki finalizacji (jak informuje! FinalizeQueue w SOS) To polecenie wprowadza w błąd; Wiedza, które obiekty znajdują się w kolejce finalizacji (sama w sobie), nie jest pomocna; Pomocna byłaby wiedza, które obiekty znajdują się w kolejce finalizacji i nadal wymagają finalizacji (czy istnieje na to polecenie?)
Wszystkie klasy DataTable, DataSet, DataView są zakorzenione w MarshalByValueComponent, finalizowanym obiekcie, który może (potencjalnie) obsługiwać niezarządzane zasoby
4 (nowe referencje):
Oryginalna odpowiedź:
Istnieje wiele mylących i ogólnie bardzo słabych odpowiedzi na ten temat - każdy, kto tu wylądował, powinien zignorować hałas i uważnie przeczytać poniższe odniesienia.
Bez wątpienia należy wywoływać Dispose na dowolnych obiektach, które można sfinalizować.
Tabele danych można sfinalizować.
Wywołanie Dispose znacznie przyspiesza odzyskiwanie pamięci.
MarshalByValueComponent wywołuje GC.SuppressFinalize (this) w swoim Dispose () - pominięcie tego oznacza konieczność oczekiwania na dziesiątki, jeśli nie setki kolekcji Gen0, zanim pamięć zostanie odzyskana:
Weź to od kogoś, kto widział 100 MB danych DataTables bez odniesienia w Gen2: jest to niezwykle ważne i całkowicie pomijane przez odpowiedzi w tym wątku.
Bibliografia:
1 - http://msdn.microsoft.com/en-us/library/ms973837.aspx
2 - http://vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD!1104.entry http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage -collector-performance-using-finalizedispose-pattern.aspx
3 - http://codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/
źródło
TableAdapter
s?Powinieneś założyć, że robi coś pożytecznego i wywołać Dispose, nawet jeśli w tej chwili nic nie robi. Wcielenia NET Framework, nie ma gwarancji, że tak pozostanie w przyszłych wersjach, prowadząc do nieefektywnego wykorzystania zasobów.
źródło
DataTable
nie jest zapieczętowane - nie jest to wielka sprawa, gdy robisznew DataTable
, ale dość ważne, gdy bierzeszDataTable
jako argument lub w wyniku wywołania metody.Nawet jeśli obiekt nie ma niezarządzanych zasobów, usunięcie może pomóc GC poprzez zerwanie wykresów obiektów. Ogólnie, jeśli obiekt implementuje IDisposable, wówczas należy wywołać metodę Dispose ().
To, czy Dispose () faktycznie coś robi, czy nie, zależy od danej klasy. W przypadku DataSet implementacja Dispose () jest dziedziczona z MarshalByValueComponent. Usuwa się z kontenera i wywołuje zdarzenie Disposed. Kod źródłowy jest poniżej (zdemontowany z .NET Reflector):
źródło
Czy sam tworzysz DataTables? Ponieważ iteracja przez elementy potomne dowolnego obiektu (jak w DataSet.Tables) zwykle nie jest potrzebna, ponieważ zadaniem rodzica jest usunięcie wszystkich jego elementów potomnych.
Ogólnie reguła jest następująca: jeśli go utworzyłeś i implementuje on IDisposable, usuń go. Jeśli NIE utworzyłeś go, NIE usuwaj go, to zadanie obiektu nadrzędnego. Ale każdy obiekt może mieć specjalne reguły, sprawdź dokumentację.
W przypadku .net 3.5 wyraźnie mówi „Zutylizuj go, gdy już nie używasz”, więc to właśnie zrobiłbym.
źródło
Wywołuję dispose za każdym razem, gdy obiekt implementuje IDisposeable. Jest tam z jakiegoś powodu.
DataSets może być ogromną pamięcią pamięci. Im szybciej zostaną oznaczone do posprzątania, tym lepiej.
aktualizacja
Minęło 5 lat, odkąd odpowiedziałem na to pytanie. Nadal zgadzam się z moją odpowiedzią. Jeśli istnieje metoda usuwania, należy ją wywołać po zakończeniu pracy z obiektem. Interfejs IDispose został zaimplementowany z jakiegoś powodu.
źródło
Jeśli twoją intencją lub kontekstem tego pytania jest naprawdę wyrzucanie elementów bezużytecznych, możesz ustawić zestawy danych i zestawy danych na jawnie null lub użyć słowa kluczowego za pomocą i pozwolić im wyjść poza zakres. Dispose niewiele robi, jak powiedział wcześniej Tetraneutron. GC będzie zbierać obiekty zestawu danych, do których już nie ma odniesienia, a także te, które są poza zakresem.
Naprawdę chciałbym, aby SO zmusiło ludzi do rezygnacji z głosowania, aby napisali komentarz przed odrzuceniem odpowiedzi.
źródło
Zestawy danych implementują IDisposable dokładny MarshalByValueComponent, który implementuje IDisposable. Ponieważ zestawy danych są zarządzane, nie ma realnych korzyści z wywoływania funkcji dispose.
źródło
Spróbuj użyć funkcji Clear (). Działa świetnie dla mnie do usuwania.
źródło
źródło