kishore
kishore

Reputation: 727

How garbage collection works on object references?

I am confused about garbage collection process on objects.

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

By calling a Dispose on variable B only, the created object will not be garbage collected as the object is still has referenced by A.

Now does the following code work same as above?

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

Now I call this static function from some other method.

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

The static function Test1 returned a reference to the Bitmap object. The reference is saved in another variable B. By calling a Dispose on B, the connection between B and object is lost but what happens to the reference that is passed from Test1. Will it remain active until the scope of the function TestB is finished?

Is there any way to dispose the reference that is passed from the static function immediately?

Upvotes: 8

Views: 5803

Answers (7)

kemiller2002
kemiller2002

Reputation: 115538

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

Upvotes: 1

Daniel Pratt
Daniel Pratt

Reputation: 12077

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?).

Upvotes: 5

Jason
Jason

Reputation: 951

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?"

Upvotes: 0

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.

Upvotes: 2

siride
siride

Reputation: 209965

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.

Upvotes: 3

Yuriy Faktorovich
Yuriy Faktorovich

Reputation: 68737

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.

Upvotes: 16

Jon Skeet
Jon Skeet

Reputation: 1503439

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.

Upvotes: 19

Related Questions