W moich zajęciach implementuję IDisposable w następujący sposób:
public class User : IDisposable
{
public int id { get; protected set; }
public string name { get; protected set; }
public string pass { get; protected set; }
public User(int UserID)
{
id = UserID;
}
public User(string Username, string Password)
{
name = Username;
pass = Password;
}
// Other functions go here...
public void Dispose()
{
// Clear all property values that maybe have been set
// when the class was instantiated
id = 0;
name = String.Empty;
pass = String.Empty;
}
}
W VS2012 moja analiza kodu mówi, aby poprawnie zaimplementować IDisposable, ale nie jestem pewien, co zrobiłem źle.
Dokładny tekst jest następujący:
CA1063 Implement IDisposable poprawnie Podaj możliwą do zastąpienia implementację Dispose (bool) w polu „User” lub oznacz typ jako zapieczętowany. Wywołanie Dispose (false) powinno tylko wyczyścić zasoby natywne. Wywołanie Dispose (true) powinno oczyścić zarówno zasoby zarządzane, jak i natywne. stman User.cs 10
Dla porównania: CA1063: poprawnie zaimplementuj IDisposable
Przeczytałem tę stronę, ale obawiam się, że tak naprawdę nie rozumiem, co należy tutaj zrobić.
Jeśli ktoś może wyjaśnić w bardziej lamerski sposób, na czym polega problem i / lub jak należy wdrożyć IDisposable, to naprawdę pomoże!
Dispose
?IDispoable
wtedy, gdy masz niezarządzane zasoby do usunięcia (obejmuje to niezarządzane zasoby, które są opakowane (SqlConnection
,FileStream
itp.) Nie można i nie należy wdrożyćIDisposable
, jeśli tylko udało zasobów, takich jak tutaj. To jest, IMO, poważny problem z analizą kodu. Jest bardzo dobry w sprawdzaniu głupich małych reguł, ale nie sprawdza się w sprawdzaniu błędów koncepcyjnych.Odpowiedzi:
To byłaby prawidłowa implementacja, chociaż nie widzę niczego, co musisz usunąć w opublikowanym kodzie. Musisz wdrożyć tylko
IDisposable
wtedy, gdy:Żadna część przesłanego kodu nie musi zostać usunięta.
źródło
using(){ }
kiedy tylko jest to możliwe, ale aby to zrobić, musisz zaimplementować IDisposable, więc ogólnie wolę mieć dostęp do klasy poprzez użycie, zwł. jeśli potrzebuję zajęć tylko w jednej lub dwóch funkcjachusing
bloku, gdy klasa implementuje IDisposable . Jeśli nie potrzebujesz jednorazowej klasy, nie wdrażaj jej. To nie ma sensu.using
bloku wydaje się być atrakcyjna poza samymIDisposable
interfejsem. Wyobrażam sobie, że było więcej niż kilka nadużyćIDisposable
wyłącznie w celu określenia zakresu.GC.SuppressFinalize(this);
jest bezcelowe. Jak zauważył @mariozski, finalizator pomógłby zapewnić, żeDispose
zostanie w ogóle wywołany, jeśli klasa nie jest używana wewnątrzusing
bloku.Przede wszystkim nie musisz „czyścić”
string
iint
-ów - zostaną one automatycznie załatwione przez garbage collectora. Jedyne, co należy wyczyścić,Dispose
to niezarządzane zasoby lub zarządzane zasoby, które implementująIDisposable
.Zakładając jednak, że jest to tylko ćwiczenie edukacyjne, zalecanym sposobem implementacji
IDisposable
jest dodanie „bezpiecznika”, aby upewnić się, że żadne zasoby nie są usuwane dwukrotnie:źródło
readonly
semantyką)Poniższy przykład przedstawia ogólne najlepsze rozwiązania dotyczące implementacji
IDisposable
interfejsu. OdniesieniePamiętaj, że potrzebujesz destruktora (finalizatora) tylko wtedy, gdy masz niezarządzane zasoby w swojej klasie. A jeśli dodasz destruktor, powinieneś pominąć Finalizację w Dispose , w przeciwnym razie spowoduje to, że twoje obiekty będą znajdować się w pamięci przez dwa cykle bezużyteczne (uwaga: przeczytaj, jak działa finalizacja ). Poniższy przykład omówi wszystko powyżej.
źródło
IDisposable
istnieje, aby zapewnić Ci środki do czyszczenia niezarządzanych zasobów, które nie będą czyszczone automatycznie przez moduł wyrzucania elementów bezużytecznych.Wszystkie zasoby, które „czyścisz”, są zasobami zarządzanymi, a zatem Twoja
Dispose
metoda nic nie daje. Twoja klasa nie powinna w ogóle implementowaćIDisposable
. Garbage Collector sam zadba o wszystkie te pola.źródło
Musisz użyć wzoru jednorazowego w następujący sposób:
źródło
SafeHandle
(i podtypy). W przypadku zarządzanych zasobów wdrożenie odpowiedniej utylizacji staje się znacznie prostsze; możesz przyciąć kod do prostej implementacjivoid Dispose()
metody.Nie musisz zajmować się swoją
User
klasą,IDisposable
ponieważ nie pobiera ona żadnych niezarządzanych zasobów (plików, połączeń z bazą danych itp.). Zwykle oznaczamy klasy tak,IDisposable
jakby miały przynajmniej jednoIDisposable
pole lub / i właściwość. Podczas implementacjiIDisposable
lepiej ująć to zgodnie z typowym schematem Microsoftu:źródło
Idisposable jest implementowane zawsze, gdy chcesz deterministycznego (potwierdzonego) wyrzucania elementów bezużytecznych.
Podczas tworzenia i używania klasy Users użyj bloku "using", aby uniknąć jawnego wywoływania metody dispose:
koniec using bloku utworzonego obiektu Users zostanie usunięty przez niejawne wywołanie metody dispose.
źródło
Widzę wiele przykładów wzorca Microsoft Dispose, który jest tak naprawdę anty-wzorcem. Jak wielu zwróciło uwagę, kod w pytaniu w ogóle nie wymaga IDisposable. Ale jeśli zamierzasz to zaimplementować, nie używaj wzorca Microsoft. Lepszą odpowiedzią byłoby postępowanie zgodnie z sugestiami zawartymi w tym artykule:
https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About
Jedyną inną rzeczą, która prawdopodobnie byłaby pomocna, jest pominięcie tego ostrzeżenia dotyczącego analizy kodu ... https://docs.microsoft.com/en-us/visualstudio/code-quality/in-source-suppression-overview?view=vs- 2017
źródło