This article says
If an object has a finalizer, it is not immediately removed when the
garbage collector decides it is no longer ‘live’. Instead, it becomes
a special kind of root until .NET has called the finalizer method.
This means that these objects usually require more than one garbage
collection to be removed from memory, as they will survive the first
time they are found to be unused.
My question is why GC don’t call finalizer when it finds that object can’t be referenced anymore and collect the object right away? why does it need more than on garbage collection?
Two points to consider:
The finalizer may take some time to complete. For example, it may end up closing a resource or something similar. You wouldn’t want that to be part of the garbage collection time, which may be blocking threads from doing work (when they just want to get some memory). By running finalization separately, the GC itself can complete very quickly, and the finalization work can be done in parallel with other work later.
The finalizer may resurrect the object by making it visible again – but detecting that would (I suspect) require another sweep of memory anyway… so why not just wait until the next time it was going to happen?