Garbage collection error in C #

I searched on google without getting what I want. I do not know that I am right or wrong. look, I'm trying to understand GC.Collect (), so here is the code.

public class SomePublisher { public event EventHandler SomeEvent; } public class SomeSubscriber { public static int Count; public SomeSubscriber(SomePublisher publisher) { publisher.SomeEvent += new EventHandler(publisher_SomeEvent); } ~SomeSubscriber() { SomeSubscriber.Count++; } private void publisher_SomeEvent(object sender, EventArgs e) { // TODO: something } } 

I do this in my main topic ..

  SomePublisher publisher = new SomePublisher(); for (int i = 0; i < 10; i++) { SomeSubscriber subscriber = new SomeSubscriber(publisher); subscriber = null; } GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine(SomeSubscriber.Count.ToString()); Console.ReadLine(); 

I get the output 0, but I should be 10 according to me, because GC.Collect () should remove the objects of class1 from memory, so class1 destructor should be called so that the counter should be increased to 10 .. can anyone explain it ..

+4
source share
2 answers

(Note also that C # does not have destructors. 1 it has finalizers. These are very different things and should not be confused.)

The "problem" is on this line:

 publisher.SomeEvent += new EventHandler(publisher_SomeEvent); 

This creates a delegate that targets the publisher_SomeEvent() method of the specific instance of the object, and adds this delegate to the call list for the publisher.SomeEvent event. This delegate object refers to the target, and this prevents the collection of the object! (This is good - if you accept a delegate to a method for a specific object, then you do not want this object to be assembled until the delegate no longer refers.)

This is technically not a problem at all, but rather, objects that support the runtime are still referenced.

To illustrate this, this is a chain of links:

 SomePublisher -+-> EventHandler --> SomeSubscriber | +-> EventHandler --> SomeSubscriber | +-> (Eight more...) 

You need to do one of two things before calling GC.Collect() :

  • Unsubscribe from an event before releasing each SomePublisher object. This will make both the EventHandler delegation instances and the SomeSubscriber instances to which they refer suitable for collection.
  • Set publisher = null; . This will make the entire graph of the object suitable for collection.

In both cases, this will release all references to SomeSubscriber objects.


1 Note that the C # specification calls these blocks of code "destructors", but it is a terrible name. Those familiar with garbage-collected languages ​​will be confused by it, since β€œfinalizer” is a common term for code that is called by the garbage collector when an object is no longer available. C ++ developers, in particular, expect the destructor to be executed at another time. So yes, C # has something called a destructor, but it is not a destructor. (Saying something fails!)

+8
source

SomeSubcriber object finalizers will not be called until the end. Since although SomeSubscriber objects are null, its SomeEvent event is still referenced by SomePublisher, which waits until the end of the application. Thus, when GC.Collect () is called, the garbage collector will not find any objects to place in the finalizer queue.

 public SomeSubscriber(SomePublisher publisher) { // publisher.SomeEvent += new EventHandler(publisher_SomeEvent); } 

If we replace the SomeSubcriber constructor with the code above, we get the result as 10 in the console.

+1
source

Source: https://habr.com/ru/post/1496728/


All Articles