25

GC is for managed objects and Finalize is for unmanaged objects thats what I have been reading. Dispose is implicit and Finalize is Explicit is what I have been reading. Can somebody give me one example of one module in which all three thing have been used for different reasons?

D'Arcy Rittich
  • 167,292
  • 40
  • 290
  • 283
Lost
  • 12,007
  • 32
  • 121
  • 193

3 Answers3

32

GC is garbage collection. It is the automatic memory management, that handles cleanup of objects allocated on the managed heap. The .NET GC employs a mark and sweep algorithm. When a garbage collection occurs it basically considers all object in the part of the heap to be cleaned as recoverable. Then it goes through a marking process where it scans for roots. I.e. it identifies objects that are still in use by the application. Having done that the remaining objects are eligible for cleanup. The heap may be compacted as part of the cleanup.

Dispose and finalizer methods both offer an option for cleaning resources, that are not handled by GC. E.g. this could be native handles and the like. They have nothing to do with reclaiming memory on the managed heap.

Dispose must be called explicitly on a type which implement IDisposable. It can be called either through the Dispose() method itself or via the using construct. The GC will not call Dispose automatically.

A finalizer or destructor (as the language specification calls it) on the other hand will automatically be called sometime after the object was eligible for cleanup. Finalize methods are executed sequentially on a dedicated thread.

Dispose() allows deterministic cleanup of resources while a finalizer can act as a safety net in case the user doesn't call Dispose().

If a type implements a finalizer, cleanup of instances is delayed as the finalizer must be called prior to cleanup. I.e. it will require an additional collect to reclaim the memory for instances of the type. If the type implements IDisposable as well, the Dispose method can be called and then the instance can remove itself from finalization. This will allow the object to be cleaned up as if it didn't have a finalizer.

If you want to dig into this, I recommend CLR via C# by Jeffrey Richter. It is a great book and it covers all the gory details of this (I left out a number of details). The new 3rd edition was just released.

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
  • 1
    +1, but you might add that you can suppress the finalizer with GC.SupressFinalize, which is something you'd want to do if you explicitly dispose the instance. – Mark Seemann Feb 26 '10 at 19:32
  • If Finalize is automatically called when an objects is eligible for cleanup then why doesn't C do that? If it is an automatic process? – Lost Feb 26 '10 at 19:34
  • It isn't called immediately. It is scheduled to be called. It may take a while before it is run. – Brian Rasmussen Feb 26 '10 at 19:37
  • @Californicated: You can get answers for all such questions by reading the article I recommended – Mark Seemann Feb 26 '10 at 19:38
  • @Californicated: C doesn't automatically do cleanup for you. That's one of the advantages of having a garbage collector in the language/runtime. – Reed Copsey Feb 26 '10 at 19:40
  • @Reed: I suspect he meant GC and not C. – Brian Rasmussen Feb 26 '10 at 20:09
  • so if we create a type which implements IDisposable, we are ok with just Dispose method, no need to add Finalize right ? – Ehsan Sajjad Mar 29 '16 at 16:33
  • 1
    @EʜsᴀɴSᴀᴊᴊᴀᴅ typically the finalizer is implemented as a fallback in case Dispose isn't called. If you do that remember to call GC.SupressFinalize from Dispose. – Brian Rasmussen Mar 29 '16 at 16:43
  • does GC pause other threads before calling finalizer? I'm asking because a finalizer may dead lock if GC actually does that. I want to know if its ok to have locks in finalizer. – M.kazem Akhgary Jan 17 '19 at 22:58
11

One of the benefits of .NET is the garbage collector. In many languages, every piece of memory must be managed by the developer- any allocated memory should eventually be released. In .NET (C#), the Garbage Collector (GC) will take care of the process of releasing memory for you. It tracks the usage of your objects, and after they become "unrooted" (ie: there are no references within your application to that object, directly or indirectly), the object's memory is automatically cleaned up.

Dispose, or more particularly, IDisposable and the Dispose pattern, is used to handle resources separately from the GC. Some resources need to be cleaned up explicitly, for various reasons. This includes using a "native" API (where .NET doesn't know about the allocated memory), using a resource that wraps native handles, etc. In order to handle this cleanly, you implement IDisposable and the Dispose pattern.

Finalization occurs on objects when they are about to be collected by the garbage collector. This provides a "safety-net" where by an object that should have been disposed can still be cleaned up, if a bit later than ideal. By implementing a finalizer, you can guarantee unmanaged resources are always released.

The problem with most samples is that there are multiple reasons to use IDisposable, and the proper implementation differs depending on the reason you are using it. For example, if you wrap a native resource directly, you should implement a finalizer, but if you encapsulate another IDisposable type, a finalizer is not necessary, even though you should still implement IDisposable. In order to address this, I've written about IDisposable and finalization in depth on my blog, describing the multiple reasons you would use IDisposable, and different patterns for different reasons.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
8

You may just want to read what I consider the definitive article on IDisposable, finalizers and garbage collection, Shawn Farkas' CLR Inside Out: Digging into IDisposable.

This article leaves very little doubt about the subject.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • 2
    Hi Mark, difference between Dipose() and other two is what I understood but where I am struggling is to understand difference between Finalize() and Garbage Collector(). because there are many articles I came across where author i saying that GC ultimately uses Finalize() to wipe out the objects. Then what is difference between keeping Finalize() in the class definition and NOT keeping one because even though I don't keep Finalize() in my class definition, GC is ultimately calling Finalize() to wipe out the unused object. – Lost Feb 26 '10 at 19:56
  • Now, somewhere I read that the objects with Finalize() will be put in "Finalization Queue" and then when the object is no longer needed then the memory is reclaimed GC. – Lost Feb 26 '10 at 19:56
  • Things seem so intermingled because GC is usign Finalize() and Finalize is using GC :). I am confused......... – Lost Feb 26 '10 at 19:58
  • The finalizer will only be invoked if it exists, and it only exists if you explicitly add it. Since finalization uses resources, that's why it's important to only add a finalizer if you truly need it. That said, you rarely need to do so - I've been writing .NET code for 8 years, and I can't remember having ever written a finalizer, but granted, I also stay away from interoperating with unmanaged code. – Mark Seemann Feb 26 '10 at 20:11
  • When an instance of a type that implements a finalizer would otherwise be eligible for cleanup it is put on the finalize queue. At this point it is not cleaned, as the finalizer must be run. At some point the finalizer thread executes the finalizer for the instance after which the instance is removed from the queue. After this it is no longer referenced and thus will be cleaned up at the next collection. – Brian Rasmussen Feb 26 '10 at 20:12
  • Okie guys, I think that wa great information haring and I am better eligible to understand the matter now. Thank you very much – Lost Feb 26 '10 at 21:34
  • i am trying to give read to whole this book, but always i fail, started once again from Chapter 1 :) – Ehsan Sajjad Mar 29 '16 at 16:47