Why call Dispose()? Memory leak won't occur?

2019-02-04 16:09发布

Edit: My question isn't getting the main answer that I was looking for. I wasn't clear. I would really like to know two things:

  1. Can NOT calling Dispose() cause memory leaks?
  2. What's the worst thing that can happen if you have a large program and never call Dispose() on any of your IDisposable objects?

I was under the impression that memory leaks could occur if Dispose() isn't called on IDisposable objects.

Per the discussion on this thread, my perception was incorrect; a memory leak will NOT occur if Dispose() isn't called.

Why ever bother calling Dispose() then? Is it just to free the resource immediately, instead of sometime later? What's the worst thing that can happen if you have a large program and never call Dispose() on any of your IDisposable objects?

7条回答
Luminary・发光体
2楼-- · 2019-02-04 16:24

Dispose is used to release non-managed resources. This could mean memory, if a class allocated non-managed memory, but it is more often native objects and resources like open files and database connections.

You often need to call Dispose on a class that itself doesn't have any non-managed resources, but it does contain another class that is disposable and may have non-managed resources.

It's also sometimes useful for developers to implement dispose to ensure deterministic finalization--guaranteeing the order in which resources are freed.

Also note that classes that implement dispose often also have a finalizer to release resourcdes if Dispose is not called. Objects with a finalizer have a different life-cycle than classes without one. When they are ready for GC, the GC will see that they have a finalizer and instead of immediately collecting the object when the GC is ready to, it puts it into the finalization queue. This means that the object lives for one extra GC iteration. When you call dispose, the implementation usually (but is not required to) calls GC.SuppressFinalize() which means the finalizer no longer needs to be called.

If a class implements IDisposable, you should always call Dispose().

查看更多
一纸荒年 Trace。
3楼-- · 2019-02-04 16:24

While some other answers seem to be suggesting that you can get away with not calling it, this is really bad advice. You should always call Dispose on any IDisposable resource.

Some .NET objects have what's called a "finalizer" - something you can define on your own classes as well, but that you rarely see done in a typical C# programmer's code. The finalizer is what runs when the garbage collector destroys the object, and sometimes it will call Dispose - but only if the implementer of the class made it that way.

The best practice is to always Dispose - no matter what. There are plenty of libraries I've used where not calling Dispose on a resource results in a memory leak, a connection leak, a operating system resource leak, or other kinds of horribleness. And the garbage collector will not reconcile the problem, because they don't implement any custom finalizer.

See related: Will the Garbage Collector call IDisposable.Dispose for me?

查看更多
老娘就宠你
4楼-- · 2019-02-04 16:27

Can NOT calling Dispose() cause memory leaks?

Yes, of course. Below is just one example.

Assume you have a main window in your application and you create a child control that has an event subscription to the main window. You unsubscribe from them on Dispose. If you don't dispose, main window can hold the reference to your child control until you close the application.

What's the worst thing that can happen if you have a large program and never call Dispose() on any of your IDisposable objects?

The worse case is not releasing some unwanted memory until you close the application.

And the other question is, what if you never implement IDisposable or finalization when they are required?

The worse case of having a memory leak is holding on to that memory until you restart the PC. This can happen only if you have un-managed resources and you don't implement dispose/finalize. If you implement Idisposable interface and implement the finalizer, finalization process will execute the Dispose for you.

Another reason why you should call Dispose is to Suppress the finalization.

As I've indicated before if there is any object with Finalize method and you didn't call the Dispose. That object can reside in memory for two GC cycles. In the first cycle, it enqueue that instance to the finalization queue and finalization happens after GC process. So, only next GC cycle can release that memory.

查看更多
混吃等死
5楼-- · 2019-02-04 16:32

The convention is that if an object implements IDisposable you should call Dispose() or use the "using" pattern. The difference between Dispose() and waiting for the destructor (finalizer) to execute is that Dispose() is called right away and can be used for freeing some important resources like db connections, files, devices, unmanaged oejects, etc.

So to summarize - if it is IDisposable - Dispose() it!

查看更多
戒情不戒烟
6楼-- · 2019-02-04 16:37

For me:

Dispose can be used in using() scope. This can help me to determine the lifespan of a IDisposeable component. I usually use this in StreamWriter/Reader or SqlConnection classes.

Another use of Dispose is it can end a lifespan of a component explicitly. Such as calling Form.Dispose() in C# winform will close the form. However, for SqlConnection, people said that just calling Dispose alone without explicitly calling Close won't guarantee the connection to be closed. Advised to call both Close and Dispose. I haven't tried this though.

And another thing, after Dispose() is called, the GC can immediaetly free the memory, because they know that the object lifespan is end, rather than waiting for the lifespan to end.

Similiar question may be C# disposing IDisposable

查看更多
霸刀☆藐视天下
7楼-- · 2019-02-04 16:42

Dispose() is intended to free resources that the garbage collector won't free, such as database connections. These resources should also be freed in the finalizer, however the finalizer is much slower than the Dispose() method.

查看更多
登录 后发表回答