How garbage collection works on object references?

浪子不回头ぞ 提交于 2019-11-30 19:06:43

I may be off, but you seem to have a misunderstanding of Dispose and garbage collection. An object will be garbage collected once all references to it are gone, in a non-deterministic way. Dispose will usually get rid of the unmanaged resources, so the object is ready to be garbage collected. In your first example, you Disposed the object, theoretically making it unusable, but it still exists on the heap and you still have a reference to it, both A and B. Once those go out of scope, the garbage collector may reclaim that memory, but not always. In example 2, a Bitmap A is placed on the heap, then you return a reference of it, and set B to that reference. Then you dispose it and B goes out of scope. At that point no more references to it exist, and it will be garbage collected at a later point.

Dispose does not garbage collect. You can't explicitly garbage collect a particular object. You can call GC.Collect() which requests that the garbage collector runs, but that's not the same. Calling Dispose doesn't even "disconnect" the object from a particular variable, in fact... while that variable remains live (up to the last time the JIT can detect that it will ever be read again) it will prevent the object from being garbage collected.

An object won't be garbage collected until it's no longer referenced by anything. Admittedly this can be earlier than you might think in some extreme cases, but you rarely need to worry about those.

It's worth being aware that Dispose and garbage collection are very different things. You call Dispose to release unmanaged resources (network connections etc). Garbage collection is solely to release memory. Admittedly garbage collection can go through finalization which may release unmanaged resources as a last resort, but most of the time you should be disposing of unmanaged resources explicitly.

It happens that Raymond Chen has just written a series of blog posts describing aspects of .NET garbage collection. This post most directly relates to your question (when are objects garbage-collected?).

Dispose() doesn't have anything to do with garbage collection. All it does is allow deterministic release of resources, but you have to call it explicitly. The object you call it on does not get garbage collected when you call Dispose(). It will be eligible for garbage collection when all the references to it are gone.

Many good answers here but I also like to point that the reason that people thought you needed IDisposable is that a GC should really be named MemoryCollector or even ManagedMemoryCollector. A GC isn't particular smart when it comes to collect non managed memory resources such as files, db conns, transactions, windows handles and so on.

One of the reason is that a managed object might have an unmanaged resource that takes several gigs of ram but to the GC it looks like 8 bytes or so.

With files, db conns and so on you often wish to close them as soon as possible to free up unmanaged resources and avoid locking issues.

With windows handles we have thread affinity to worry over. As a GC runs in a dedicated thread that thread is always the wrong thread for freeing windows handles.

So GC helps alot to avoid leaking managed memory and reduce code clutter but one still should release unmanaged resources ASAP.

using () statement is a blessing.

PS. Quite often I implement IDisposable even though I don't have any direct unmanaged resources, its importsnt though to inform all member variables that implement IDisposable that Dispose been called.

Ok for starters Dispose != Garbage Collected. You can call dispose and never have it Garbage collected, because a "Disposed Object" can still have references to it. The dispose method is used to "Tidy Up" the object before the CG runs (close open db connections, or file connections etc.).

object A = new object();
object B = A;        
B.Dispose();

In this instance B.Dispose is calling the dispose method on A, because B is referencing the object in variable A. Neither will be CGd, because they haven't fallen out of scope yet.

public static image Test1()
{
    Bitmap A = new Bitmap();
    return A;
}

What is happening here is that you are creating object A and returning it, so when you leave Test1, A is most likely being referenced by another variable in the calling method. This means that even though you have left the method, A is still rooted (most likely) and won't be CG'd until the calling method is done with it.

public void TestB()
{
   Bitmap B = Test1();
   B.Dispose();
} 

Here B is being created and calling dispose. This does not mean that it will be gargable collected. Once the program leaves the method, B falls out of scope meaning that it can be collected next time the GC is called.

When to use Dispose

It may be worth noting that calling Dispose may, in fact, do nothing at all. It gives the object a chance to clean up resources such as database connections and unmanaged resources. If you have an object that contains an unmanaged resource such as a database connection, Dispose will tell the object it is time to clean up those references.

The fundamental question in garbage collection is, "Can this object be reached?" As long as there is on object on the stack that has a reference to your object (or there is a reference to this object somewhere in the object hierarchy), the object won't be garbage collected.

Example:

ObjA creates an ObjB, which creates an ObjC. Obj C will not be garbage collected until it is no longer referenced by ObjB, or until ObjB is no longer referenced by ObjA, or until there are no objects that retain a reference to ObjA.

Again, the question to ask is, "Can this object currently be referenced by anything in the code?"

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!