|Monte on Dec 15, 2008 at 12:07:08 PM (# 9)|
But couldn't I circumvent that by explicitly calling GC.Collect()?
MHenke on Dec 16, 2008 at 2:18:54 AM (# 10)
It's not that I know too much on C#, but I'd assume that GC.Collect() starts a complete GC cycle, whereas Dispose() explicitely releases the resources of the specific object. In general, a complete GC cycle will be much more expensive. Tho the GC will run anyway, chances are that it'll run when the system isn't too busy. So, it's the decision who know's better when's the best time to perform the (complete) GC.
This surely depends on the application. But it's not inprobable that you know beter when to dispose a single object, whereas the system knows better when to perform the general GC stuff.
brian on Dec 17, 2008 at 1:14:46 AM (# 11)
The GC.Collect(), does an immediate collection of garbage. As a rule, you don't need it unless you are allocating loads of objects in a method as it will be cleaned up eventually anyway. The GC is fairly efficient in its automatic cleaning process. Dispose() is needed for certain components where they load resources and you don't need or want them to be locked. A great example of this is the Image.FromFile call. This returns an image object that has the specified file loaded for manipulation. If you do not dispose this object when done it actually locks the file for about 1/2 hour - connected to the GC run cycle. However, a GC.Collect() doesn't unlock the file either - it has to be disposed of. I found this out the hard way when I was not disposing of bitmaps/images when overlaying text on them and found the files to be locked.
Streams are also similar, you need to perform a close and also a dispose();
As a rule though, for things like database connections and readers, as long as you close them you don't need a dispose call.
If you are concerned about memory or have methods with loads of objects, a GC.Collect(); wouldn't hurt. If you are using the method within a loop DO NOT call the GC.Collect at the end of the method but rather call it once the loop is finished. It's an efficiency thing - this all depends on how much memory you're using though. I'd recommend checking out the SDK help for more info and there is a way to see how much memory methods are using for debug purposes.
Working with large images and arrays might be one example of needing to do a collect but I can count on one hand how many times I've used it in my current project. Dispose is the important one, mostly.
Monte on Dec 17, 2008 at 9:26:34 AM (# 12)
So then when should I use objMyObject = null; ?
brian on Dec 17, 2008 at 11:15:39 PM (# 13)
That is the beauty of C# - You don't have to. Of course if you want to keep in the habit of doing things the c++ way you can but for objects without a dispose you really don't need to, they will automatically be destroyed when the method is completed and then the GC will clean them up at some point.
ChrisRickard on Jan 6, 2009 at 5:03:50 PM (# 14)
Sorry to chime in on this so late, I didn't even know SE was down for so long.
Brian is right on, Dispose is really nothing like setting objects to null or getting garbage collection. c++ kind of made people associate freeing memory with releasing other resources. In reality we have so much memory nowadays and with the use of garbage collection we really don't need to worry about managing memory. However things like database connections, file handles, and other such things are still considered extremely expensive to keep open and should be released as early as possible.
Now of course IDisposable is merely an interface, but most developers follow the same pattern. Dispose releases any expensive resources, and usually makes the object itself useless afterwards.
Where Dispose and Finalizers (garbage collection) meet is when a developer does a nice thing and automatically calls Dispose upon destruction in case the calling code forgets to call it. This ensures no resource leaks, but resources can still be held for too long causing slowdowns and possibly locking problems of some kind. However in general it's best not to group the 2 concepts together. People that have only programmed in non-memory managed systems tend to get caught up with this and obsess over ways to get deterministic finalization when it's not really necessary.
Now one place where you may want to explicitly set an object reference to null is in a scenario like this:
private void someMethod()
BigObject myBigObject = new BigObject(); // Allocates 350mb of memory for some reason
// We're done with myBigObject but the reference is still active so it won't be garbage collected
[Some long running process goes here]
In this case a significant amount of memory won't be freed when it could be. Setting it to null before the long running process makes it available for garbage collection. However these situations should be rare because if an object does acquire that much memory it makes sense to implement IDisposable so that the memory can be explicitly freed (probably from a MemoryStream). Also usually the .NET runtime (possibly compiler optimizations as well) is pretty smart about when an object is really not being used anymore and may GC the object even before it technically goes out of scope.
ChrisRickard on Jan 6, 2009 at 5:12:27 PM (# 15)
Also don't call GC.Collect() unless you really know what you're doing. The Garbage collection algorithm is smart about when to release memory. Forcing it to GC will usually hurt performance because it makes it free memory at a time which probably isn't the optimal time to do so. If you're running out of memory there's probably something else you need to optimize. If you're forced to GC to release non-memory resources that means someone either isn't calling Dispose or someone wrote an object that should implement it.