Jeśli mam następujący kod:
MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;
Czy pClass będzie zbierany śmieci? Czy też będzie się kręcił, wciąż odpalając wydarzenia, gdy tylko się pojawią? Czy muszę wykonać następujące czynności, aby umożliwić zbieranie śmieci?
MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;
c#
.net
event-handling
garbage-collection
Mark Ingram
źródło
źródło
Odpowiedzi:
W przypadku konkretnego pytania „Czy pClass zostanie wyrzucony”: subskrypcja zdarzenia nie ma wpływu na zbieranie pClass (jako wydawcy).
W przypadku GC ogólnie (w szczególności celu): zależy od tego, czy MyFunction jest statyczna czy oparta na instancji.
Delegat (na przykład subskrypcja zdarzenia) do metody instancji zawiera odwołanie do instancji. Tak więc, subskrypcja wydarzenia zapobiegnie GC. Jednak gdy tylko obiekt publikujący zdarzenie (pClass powyżej) kwalifikuje się do kolekcji, przestaje to stanowić problem.
Zauważ, że jest to jednokierunkowe; tj. jeśli mamy:
wtedy „wydawca” utrzyma „cel” przy życiu, ale „cel” nie utrzyma przy życiu „wydawcy”.
Więc nie: jeśli pClass i tak zostanie zgromadzony, nie ma potrzeby anulowania subskrypcji słuchaczy. Jednakże, jeśli pClass był długowieczny (dłużej niż instancji z MyFunction), następnie pClass mógł utrzymać tę instancję żyje, więc to będzie konieczne, aby wypisać się, jeśli chcesz cel mają być zebrane.
Z tego powodu zdarzenia statyczne są jednak bardzo niebezpieczne, gdy są używane z programami obsługi opartymi na instancjach.
źródło
WeakReference
, aw niektórych przypadkach może to być dobry pomysł, ale tak często, jak nie, będzie to silny pomysł.Tak, pClass będzie śmieciami. Subskrypcja zdarzenia nie oznacza, że istnieje odwołanie do pClass.
Tak więc nie będziesz musiał odłączać modułu obsługi, aby pClass mógł zostać wyrzucony.
źródło
W momencie, gdy pamięć nie jest już przywoływana, staje się kandydatem do odśmiecania. Kiedy wystąpienie klasy wykracza poza zakres, program nie odwołuje się do niej. Nie jest już używany i dlatego można go bezpiecznie zebrać.
Jeśli nie jesteś pewien, czy coś zostanie zebrane, zadaj sobie następujące pytanie: czy nadal istnieje odniesienie do tego? Do procedur obsługi zdarzeń odwołuje się instancja obiektu, a nie odwrotnie.
źródło
pClass
będą zbierane śmieci. Jednakże, jeśli kod snippet powyżej znajduje się wewnątrz innej klasy, instancja tej klasy nie mogą być usunięte, jeśli nie zostanie ustawionapClass
nanull
.źródło