Embarrassed. Is CA1063 invalid? GC.SuppressFinalize (this)

I have a simple MyDataClass class with a member (obj) that implements IDisposable:

public class MyDataClass : IDisposable { private DisposableObject obj; private List<string> list; private int c; public MyDataClass() { obj = new DisposableObject(); list = new List<string>(); c = 114; } public void Dispose() { obj.Dispose(); } } public class DisposableObject : IDisposable { public void Dispose() { // Free resource Console.WriteLine("Dispose DisposableObject"); } } 

When I start the code analysis, I get warning CA1063, which shows me that I should call the GC.SuppressFinalize () method in the Dispose () method in MyDataClass .

And I'm really confused by this CA1063 warning. Because, as far as I know, I have to call GC.SuppressFinalize () to tell the garbage collector:

"Hey GC, don’t worry about this facility because I already did all the cleaning for you!"

So, please confirm whether I am mistaken or not. If I add GC.SuppressFinalize () , I will get rid of CA1063, but this will cause the GC to not clear my object. Therefore, I will have a memory leak, because other members of the class (managed code) will not be cleared.

+7
source share
3 answers

If I add GC.SuppressFinalize() , I will get rid of CA1063 but this will cause the GC to not clear my object.

No, your objects will still be collected.

"Hey GC, don’t worry about this facility because I already did all the cleaning for you!"

Actually you say: do not worry about the Finalizer (destructor) of this object. If he is.

And in this case, Code Analysis is wrong: your class has an IDisposable.Dispose() method, but it does not have a destructor. Thus, a warning is pointless, being more protective and triggered for the wrong reason. Disable or ignore it.

+2
source

The GC.SuppressFinalize() method tells the VM not to start the finalizer. This is a fun way in C #:

~MyDataClass()

To remove the warning, you need to either pin your class or implement the full IDisposable pattern .

+5
source

It feels like you're still embarrassed even though you accepted the answer. Let me explain:

The garbage collector (GC) has the unenviable task of removing any objects from memory that are inaccessible.

reachability

Object A is accessible only when there is any chain of links from any GC-root to the object. Examples of roots are the stack and any static fields. Thus, to determine if A reachable, all that the GC requires is to find a link on the stack that references an object that has a reference related to an object ... that refers to object A If he cannot find such a chain, object A inaccessible. one

So, once the GC determines that A unavailable, it will want to remove it from memory. However, before he does, GC will check if A finalizer ( ~A ) that needs to be started. If not, it removes A from memory, and GC executes with it.

Completion

However, if A has a finalizer to be launched, it cannot delete the object from memory until the finalizer completes. Thus, it adds a reference to A in the finalizer queue and does not delete the object from memory (for now). The garbage collector now works with A However, when the GC starts up again, it will again try to determine if A is available. Fortunately, the finalizer queue is also one of the roots of the garbage collector, so it determines that there is a link from the finalizer queue to A , so A reachable and will not be deleted from memory again.

Next comes the finalizer thread, a thread that periodically checks to see if there are any objects in the finalizer queue. If there is, he chooses one and runs his finalizer method. In the end, the finalizer thread will run finalizer A Once this is done, the reference to A will be removed from the finalizer queue.

Cleaning

Then, after some time, the garbage collector starts up again and again tries to determine if A is available. Since it is currently not mentioned anywhere, not even from the finalizer queue, A not available. GC removes A from memory.


As you can see, usually the GC can delete inaccessible objects in the same collection cycle that it detects, but when the object has a finalizer to be launched, it can take several cycles for the collected object. Therefore, CA1063 recommends placing GC.SuppressFinalize() in the Dispose method so that the GC knows that objects do not need to be modified before they are deleted from memory. Thus, object 2 is always deleted from memory.

Note that when you don’t have a finalizer, you do not need to add GC.SuppressFinalize() , so the CA1063 warning is a little redundant in this regard.

More information on the garbage collector can be found in this MSDN article .


1 ) Reachability is the reason why links to null are usually set after they are removed. This makes the reference object the most likely unreachable, and therefore the candidate to be deleted.

2 ) . It is possible (but not recommended) to resurrect A using the finalizer to add a reference to A from another object with an achievement or root (for example, a static field). This allows A accessible again, and the garbage collector will not delete it. However, its finalizer will not start again, as it has already been called once.

+3
source

All Articles