What is IDisposable for?

2019-01-07 21:26发布

If .NET has garbage collection then why do you have to explicitly call IDisposable?

6条回答
可以哭但决不认输i
2楼-- · 2019-01-07 21:35

Because Objects sometime hold resources beside memory. GC releases the memory; IDisposable is so you can release anything else.

查看更多
冷血范
3楼-- · 2019-01-07 21:38

Garbage collection is for memory. You need to dispose of non-memory resources - file handles, sockets, GDI+ handles, database connections etc. That's typically what underlies an IDisposable type, although the actual handle can be quite a long way down a chain of references. For example, you might Dispose an XmlWriter which disposes a StreamWriter it has a reference to, which disposes the FileStream it has a reference to, which releases the file handle itself.

查看更多
叛逆
4楼-- · 2019-01-07 21:45

In order to use the using keyword the object must implement IDisposable. http://msdn.microsoft.com/en-us/library/yh598w02(VS.71).aspx

查看更多
劫难
5楼-- · 2019-01-07 21:52

because you want to control when the resources held by your object will get cleaned up.

See, GC works, but it does so when it feels like it, and even then, the finalisers you add to your objects will get called only after 2 GC collections. Sometimes, you want to clean those objects up immediately.

This is when IDisposable is used. By calling Dispose() explicitly (or using thr syntactic sugar of a using block) you can get access to your object to clean itself up in a standard way (ie you could have implemented your own cleanup() call and called that explicitly instead)

Example resources you would want to clean up immediately are: database handles, file handles, network handles.

查看更多
贼婆χ
6楼-- · 2019-01-07 21:55

Expanding a bit on other comments:

The Dispose() method should be called on all objects that have references to un-managed resources. Examples of such would include file streams, database connections etc. A basic rule that works most of the time is: "if the .NET object implements IDisposable then you should call Dispose() when you are done with the object.

However, some other things to keep in mind:

  • Calling dispose does not give you control over when the object is actually destroyed and memory released. GC handles that for us and does it better than we can.
  • Dispose cleans up all native resources, all the way down the stack of base classes as Jon indicated. Then it calls SuppressFinalize() to indicate that the object is ready to be reclaimed and no further work is needed. The next run of the GC will clean it up.
  • If Dispose is not called, then GC finds the object as needing to be cleaned up, but Finalize must be called first, to make sure resources are released, that request for Finalize is queued up and the GC moves on, so the lack of a call to Dispose forces one more GC to run before the object can be cleaned. This causes the object to be promoted to the next "generation" of GC. This may not seem like a big deal, but in a memory pressured application, promoting objects up to higher generations of GC can push a high-memory application over the wall to being an out-of-memory application.
  • Do not implement IDisposable in your own objects unless you absolutely need to. Poorly implemented or unneccessary implementations can actually make things worse instead of better. Some good guidance can be found here:

    Implementing a Dispose Method

    Or read that whole section of MSDN on Garbage Collection

查看更多
劫难
7楼-- · 2019-01-07 22:01

The IDisposable interface is often described in terms of resources, but most such descriptions fail to really consider what "resource" really means.

Some objects need to ask outside entities to do something on their behalf, to the detriment of other entities, until further notice. For example, an object encompassing a file stream may need to ask a file system (which may be anywhere in the connected universe) to grant exclusive access to a file. In many cases, the object's need for the outside entity will be tied to outside code's need for the object. Once client code has done everything it's going to do with the aforementioned file stream object, for example, that object will no longer need to have exclusive access (or any access for that matter) to its associated file.

In general, an object X which asks an entity to do something until further notice incurs an obligation to deliver such notice, but can't deliver such notice as long as X's client might need X's services. The purpose of IDisposable is to provide a uniform way of letting objects know that their services will no longer be required, so that they can notify entities (if any) that were acting on their behalf that their services are no longer required. The code which calls IDisposable need neither know nor care about what (if any) services an object has requested from outside entities, since IDisposable merely invites an object to fulfill obligations (if any) to outside entities.

To put things in terms of "resources", an object acquires a resource when it asks an outside entity to do something on its behalf (typically, though not necessarily, granting exclusive use of something) until further notice, and releases a resource when it tells that outside entity its services are no longer required. Code that acquires a resource doesn't gain a "thing" so much as it incurs an obligation; releasing a resource doesn't give up a "thing", but instead fulfills an obligation.

查看更多
登录 后发表回答