views:

211

answers:

4

Hi All,

I am relatively new to .net. As I was trying to grasp the concept of Garbage Collection(from "CLR via C#"), I came to know how strong is the Garbage collection approach. But then as I read I understood that native resources allocated should be released. The methods are:
i) Making our type derive from CriticalFinalizerObject type
ii) Using Dispose Pattern using the using statement

Questions in my mind:
1) I am bit confused when to use what?
2)Also isn't it more heavy for the CLR to shift the non-garbage objects down to compact the heap?
3) Any other article suggestion for reading and understanding the concept more thoroughly.

Please correct me if I am mistaken in any of my above statements
Regards,
Justin Samuel.

+2  A: 

Use the Dispose pattern and using when you can. Use finalizers only if you have no way to deterministically know when your special resources can be freed. If you find that this happens often, you are probably doing something wrong.

Garbage collection is a deep topic. For an overview of garbage collection in general and its implementation in the CLR in particular, this article seems solid. It's from almost ten years ago, but good CS is like good math: it ages well.

David Seiler
+2  A: 

I recommend this article on Dispose, Finalization, and Resource Management.

What you use depends a lot on what type of programming you do. Based on personal experiences, I've found:

  • Most of the time the only resource management I have to do is wrap any object that implements IDisposable in a using block.
  • Occasionally I have to implement the Basic Dispose Pattern (no finalizer) when my class owns an object that implements IDisposable.
  • I have never had to derive from CriticalFinalizerObject.

Your mileage may vary.

TrueWill
A: 

Safely working with unmanaged handles

Reliably releasing unmanaged handles without constrained execution regions (CERs) is not possible. You always end up with a race condition, since a ThreadAbort or OutOfMemory exception can come in the middle of your finalizer. So you need to use CERs.

CriticalFinalizerObject uses Constrained Execution Regions internally, is prioritized during finalization, and has some other features that make it relatively easy to "get it right" and always release unmanaged resources when they need to be. In general you should derive from SafeHandle or CriticalFinalizerObject when holding handles to unmanaged objects. That way you know they will be cleaned up when your object is garbage collected, even if it is an unusual shutdown situation like a ThreadAbortException.

What using() and IDisposable adds

using() and the IDisposable pattern allow you to release unmanaged resources eagerly - as soon as you are done using them. If you don't dispose your objects with using(), they will stick around until the next garbage collection. This is inefficiency.

So CriticalFinalizerObject is about making sure unmanaged resources are eventually released whereas using() is about making sure unmanaged resources are released quickly. Both should be used together.

Also using() is good to use in pure managed code, for example if you are caching a pool of objects the Dispose() can return the object to the pool.

Compacting the heap during GC

Compacting the heap can be more efficient because the objects that last a long time end up all packed together. In NET Framework only the lowest generation (the most recently created objects) are compacted agressively. Theres is a lot of optimization done under the hood. It is fun to read up on, but not important for getting work done. If you want to read more about it, search for articles on "generational garbage collection."

Ray Burns
+3  A: 
  1. You want to derive from CriticalFinalizerObject in the case where the usage of your type should be treated as a constrained execution region or CER for short. A CER is an area of code that must complete without exception and in my experience they are not used that often (but that doesn't mean they aren't useful).

    Implementing the IDisposable interface is a bit different - this interface offers a deterministic way of cleaning up after your type once the consumer of it no longer needs it. This is often used to clean up unmanaged resources (like database connections and file handles).

  2. Yes, the garbage collector will have to move many objects in memory during its compact phase but this isn't really something that can be helped. Objects will be moved when virtual memory becomes fragmented and this is something that is outside of your control since the garbage collector is completely responsible for the managed heap. The best practice in this case is to build your types to work as best as possible and only worry about the garbage collector when instrumentation proves that it has become an issue.

  3. I will see if I can find some more helpful articles but CLR via C# is pretty much the best information you will be able to find on this topic.

Andrew Hare
Yes Andrew, you are right. "CLR via C#" is an excellent resource for learning .net conceptually. Can you suggest me good links to learn c# concepts.
Justin