Witam. Mam taki problem, ponieważ instrukcje z destruktora nie są wypisywane w konsoli. Co zrobić, aby w konsoli zobaczyć tekst podany w destruktorze? Jeśli to ma jakieś znaczenie to korzystam z Visual Studio na MacOS.
A po co chcesz zrobić coś takiego? Poleganie na garbage kolektorze żeby wywołać jakąś logikę jest... wątpliwy.
Riddle napisał(a):
A po co chcesz zrobić coś takiego?
Próbuje ogólnie znaleźć zastosowanie destruktora i zobaczyć jak działa
Maciek_SK8 napisał(a):
Riddle napisał(a):
A po co chcesz zrobić coś takiego?
Próbuje ogólnie znaleźć zastosowanie destruktora i zobaczyć jak działa
No to jego zastosowanie raczej jest ograniczone.
Nie można ich wywołać "po prostu", są wołane w momencie w którym nie ma już sposobu żeby skorzystać z obiektu, czyli np kiedy wszystkie referencje do niego już znikną.
Czekaj, czekaj, To C# ma destruktory? Destruktory są zwykle dla obiektów ręcznie zarządzanych, ewentualnie zarządzanych przez liczenie referencji. No ale .NOT ma chyba bardzie rozbudowany system sprzątania śmieci więc wtedy destruktor może być wywołanykiedyś później w skrajnym wypadku nigdy bo program się skończył,
KamilAdam napisał(a):
Czekaj, czekaj, To C# ma destruktory? Destruktory są zwykle dla obiektów ręcznie zarządzanych, ewentualnie zarządzanych przez liczenie referencji. No ale .NOT ma chyba bardzie rozbudowany system sprzątania śmieci więc wtedy destruktor może być wywołanykiedyś później w skrajnym wypadku nigdy bo program się skończył,
W c# destruktory są wołane przez garbage-collector kiedy już nie ma żadnej referencji do obiektu. Przy okazji destruktory z tego co pamiętam wołają Finalize
.
Tak czy tak, ich użyteczność jest raczej niska.
Jeśli chcesz ogarniać co ma się stać z otwartymi zasobami to lepiej użyć bloku using
np.
Maciek_SK8 napisał(a):
Riddle napisał(a):
A po co chcesz zrobić coś takiego?
Próbuje ogólnie znaleźć zastosowanie destruktora i zobaczyć jak działa
Nie wiem jak w .NET, ale w JVM od lat mówi się że destruktorów (zwanych tam finalizerami) nie należy dotykać(używać/nadpisywać) . Pamietam dwa powody:
- Nie mamy pewności kiedy destruktor zostanie wykonany
- umieszczanie kodu w destruktorze spowalnia sprzątanie sterty
Riddle napisał(a):
KamilAdam napisał(a):
Czekaj, czekaj, To C# ma destruktory? Destruktory są zwykle dla obiektów ręcznie zarządzanych, ewentualnie zarządzanych przez liczenie referencji. No ale .NOT ma chyba bardzie rozbudowany system sprzątania śmieci więc wtedy destruktor może być wywołanykiedyś później w skrajnym wypadku nigdy bo program się skończył,
W c# destruktory są wołane przez garbage-collector kiedy już nie ma żadnej referencji do obiektu. Przy okazji destruktory z tego co pamiętam wołają
Finalize
.Tak czy tak, ich użyteczność jest raczej niska.
Jeśli chcesz ogarniać co ma się stać z otwartymi zasobami to lepiej użyć bloku
using
np.
Czyli nie warto używać destruktora na podstawowym poziomie?
Maciek_SK8 napisał(a):
Riddle napisał(a):
KamilAdam napisał(a):
Czekaj, czekaj, To C# ma destruktory? Destruktory są zwykle dla obiektów ręcznie zarządzanych, ewentualnie zarządzanych przez liczenie referencji. No ale .NOT ma chyba bardzie rozbudowany system sprzątania śmieci więc wtedy destruktor może być wywołanykiedyś później w skrajnym wypadku nigdy bo program się skończył,
W c# destruktory są wołane przez garbage-collector kiedy już nie ma żadnej referencji do obiektu. Przy okazji destruktory z tego co pamiętam wołają
Finalize
.Tak czy tak, ich użyteczność jest raczej niska.
Jeśli chcesz ogarniać co ma się stać z otwartymi zasobami to lepiej użyć bloku
using
np.Czyli nie warto używać destruktora na podstawowym poziomie?
Raczej nie.
Maciek_SK8 napisał(a):
Riddle napisał(a):
A po co chcesz zrobić coś takiego?
Próbuje ogólnie znaleźć zastosowanie destruktora i zobaczyć jak działa
Nie jest to właściwie destruktor (jak w C++), bo nie jest deterministyczny ... lepszym słowem, choć nie idealnym, jest finalizer.
"Obserwacja" tego jest dośc trudna, bo zależy od odśmiecacza
Riddle napisał(a):
Jeśli chcesz ogarniać co ma się stać z otwartymi zasobami to lepiej użyć bloku
using
np.
To ważne, z ważnym ALE.
Użycie using nie wpływa za specjalnie na prawdziwą destrukcję (pozbawiony referencji będzie się gdzieś plątał aż GC go usunie), ale o ile klasa implementuje IDisposable
to wykonanie metody Dispose.
Fakt, to ma implementować przygotowanie do śmierci, ale na poziomie języka to jest aż i tylko jeszcze jeden interfejs i jeszcze inne metoda normalnych, ciągle żywych obiektów. Powinno to być zwolnie zasobów, które instancja obiektu posiada.
Takie spisanie testamentu / darowizna przed śmiercią
Java wprowadziła analogiczny pomysł później, nazywa try with resources, a implementowanym interfejsem ma być java.lang.AutoCloseable
O ile historycznie kopiowanie zachodziło Java -> C#, to tutaj jedno z lepszych kopiowań w odwrotną stronę.
ZrobieDobrze napisał(a):
Riddle napisał(a):
Jeśli chcesz ogarniać co ma się stać z otwartymi zasobami to lepiej użyć bloku
using
np.To ważne, z ważnym ALE.
Użycie using nie wpływa za specjalnie na prawdziwą destrukcję (pozbawiony referencji będzie się gdzieś plątał aż GC go usunie), ale o ile klasa implementujeIDisposable
to wykonanie metody Dispose.Fakt, to ma implementować przygotowanie do śmierci, ale na poziomie języka to jest aż i tylko jeszcze jeden interfejs i jeszcze inne metoda normalnych, ciągle żywych obiektów. Powinno to być zwolnie zasobów, które instancja obiektu posiada.
Takie spisanie testamentu / darowizna przed śmierciąJava wprowadziła analogiczny pomysł później, nazywa try with resources, a implementowanym interfejsem ma być
java.lang.AutoCloseable
O ile historycznie kopiowanie zachodziło Java -> C#, to tutaj jedno z lepszych kopiowań w odwrotną stronę.
using
nie ma na celu żadnego udawania "przygotowania do smierci", tylko to po prostu konstrukt języka wywołujący operację symetryczną, typu otwarcie i zamknięcie pliku, założenie locka i ściągnięcie locka. Nie ma nic wspólnego z destruktorami ani gargabe-collectorem.
Czyli nie warto używać destruktora na podstawowym poziomie?
Na żadnym nie warto tego używać jako coś normalnego.
To jest prędzej coś, co może się w bardzo specyficznych i pojedynczych przypadkach przydać
czyli czytaj to jako: raz na kilka lat robiąc coś nietypowego.
1a2b3c4d5e napisał(a):
Czyli nie warto używać destruktora na podstawowym poziomie?
Na żadnym nie warto tego używać jako coś normalnego.
To jest prędzej coś, co może się w bardzo specyficznych i pojedynczych przypadkach przydać
czyli czytaj to jako: raz na kilka lat robiąc coś nietypowego.
Okok dzięki bardzo za odpowiedz
Wywołaj GC:
klasa = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Jak już, to najlepiej GC.Collect(2, GCCollectionMode.Forced);
, aby zamieść wszystkie generacje śmieci i wymusić uruchomienie.
Podstawowa różnica jest taka, że w C++ to programista decyduje o momencie zniszczenia obiektu, a w C# to system o tym decyduje. Jeżeli w klasie definiujesz coś, co nie jest tylko danymi w pamięci (np. otwarcie pliku, otwarcie gniazd sieciowego itp.), to zaimplementuj "destruktor" w metodzie Dispose, klasa musi implementować interfejs IDisposable, a tworzenie obiektu powinno być z użyciem using
.
Można mniej więcej coś takiego, można nawet zabezpieczyć przed przypadkowym wywołaniem czegoś po uruchomieniu Dispose, gdyby z jakiś powodów nie można było użyć z wykorzystaniem using
. Dla pewności można dodać wywołanie Dispose w destruktorze.
class SomeClass : IDisposable
{
bool IsDisposed;
public SomeClass()
{
IsDisposed = false;
}
~SomeClass()
{
Dispose();
}
public void SomeWork()
{
if (IsDisposed) throw new Exception("SomeClass object is disposed");
SomeCode();
}
public void Dispose()
{
if (!IsDisposed)
{
IsDisposed = true;
SomeDisposeCode();
}
}
}