Since .NET has a garbage collector why do we need finalizers/destructors/dispose-pattern?

前端 未结 12 1562
粉色の甜心
粉色の甜心 2020-12-07 09:09

If I understand correctly the .net runtime will always clean up after me. So if I create new objects and I stop referencing them in my code, the runtime will clean up those

相关标签:
12条回答
  • 2020-12-07 09:47

    Some objects might need to clean up low-level items. Such as hardware that needs to be closed, etc.

    0 讨论(0)
  • 2020-12-07 09:48
    1. There are things the garbage collector can't clean up after you
    2. Even with things it can cleanup, you can help it clean up sooner
    0 讨论(0)
  • 2020-12-07 09:53

    The simplistic explanation:

    • Dispose is designed for deterministic disposal of non-memory resources, especially scarce resources. For example, a window handle or a database connection.
    • Finalize is designed for non-deterministic disposal of non-memory resources, usually as a backstop if Dispose wasn't called.

    Some guidelines for implementing the Finalize method:

    • Only implement Finalize on objects that require finalization, because there is a performance cost associated with Finalize methods.
    • If you require a Finalize method, consider implementing IDisposable to allow users of your type to avoid the cost of invoking the Finalize method.
    • Your Finalize methods should be protected rather than public.
    • Your Finalize method should free any external resources that the type owns, but only those that it owns. It should not reference any other resources.
    • The CLR doesn't make any guarantees as to the order in which Finalize methods are called. As Daniel notes in his comment, this means that a Finalize method should not access any member reference types if possible, because these may have (or may one day have) their own finalizers.
    • Never call a Finalize method directly on any type other than the type's base type.
    • Try to avoid any unhandled exception in your Finalize method, as that will terminate your process (in 2.0 or higher).
    • Avoid doing any long-running task in your Finalizer method, as that will block the Finalizer thread and prevent other Finalizer methods being executed.

    Some guidelines for implementing the Dispose method:

    • Implement the dispose design pattern on a type that encapsulates resources that explicitly need to be freed.
    • Implement the dispose design pattern on a base type that has one or more derived types that hold on to resources, even if the base type does not.
    • After Dispose has been called on an instance, prevent the Finalize method from running by calling the GC.SuppressFinalize Method. The only exception to this rule is the rare situation in which work must be done in Finalize that is not covered by Dispose.
    • Do not assume that Dispose will be called. Unmanaged resources owned by a type should also be released in a Finalize method in the event that Dispose is not called.
    • Throw an ObjectDisposedException from instance methods on this type (other than Dispose) when resources are already disposed. This rule does not apply to the Dispose method because it should be callable multiple times without throwing an exception.
    • Propagate the calls to Dispose through the hierarchy of base types. The Dispose method should free all resources held by this object and any object owned by this object.
    • You should consider not allowing an object to be usable after its Dispose method has been called. Recreating an object that has already been disposed is a difficult pattern to implement.
    • Allow a Dispose method to be called more than once without throwing an exception. The method should do nothing after the first call.
    0 讨论(0)
  • 2020-12-07 09:53

    There are a few (very few) cases where it may be necessary to perform a specific action when a pure managed object is no longer used, I can't come up with an example off the top of my head but I have seen a couple of legitimate uses over the years. But the main reason is to clean up any unmanaged resources that the object might be using.

    So, in general, you won't need to use the Dispose/Finalize pattern unless you are using unmanaged resources.

    0 讨论(0)
  • 2020-12-07 09:54

    The previous answers are good but let me emphasize the important point here once again. In particular, you said that

    If I understand correctly the .net runtime will always clean up after me.

    This is only partly correct. In fact, .NET only offers automatic management for one particular resource: main memory. All other resources need manual cleanup.1)

    Oddly, main memory gets special status in almost all discussions about program resources. There's of course a good reason for this – main memory is often the scarcest resource. But it's worth remembering that there are other types of resources as well, that also need managing.


    1) The usual attempted solution is to couple the lifetime of other resources to the lifetime of memory locations or identifiers in the code – hence the existence of finalizers.

    0 讨论(0)
  • 2020-12-07 09:54

    Mainly for non-managed code, and interaction with non-managed code. "Pure" managed code should never need a finalizer. Disposable on the other hand is just a handy pattern to force something to be released when you are done with it.

    0 讨论(0)
提交回复
热议问题