简体   繁体   中英

How certain types like Image can be Dispose using the Dispose() method

Let's say I have a large Image object, if I call the Dispose() method of this object I can easily see the memory consumption of my application be reduced, since I just cleared the object from memory.

But what if I have my own type/class and want to dispose an instance of it, which, let's say, contains a byte[] array (which I think is the same thing the Image class has internally). How would I go about implementing IDisposable so when Dispose() is called the byte[] is instantly disposed from memory. Without me having to wait for GC ?

What if it were a string instead of a byte[] ?

Objects in .NET only exist as long as some sort of reference exists to them. Objects that don't exist don't hold references to anything. If during a garbage-collection cycle an object is found to have no references to it anywhere except as WeakReference targets, the system will invalidate those WeakReference objects, whereupon the objects will no longer have any references pointing to them and will thus cease to exist. If the only non-weak references to an object are in the system's list of objects that have registered Finalize methods, the object will be removed from that list and added to the system's list of objects whose Finalize method should be run at first opportunity. Once the system run's an object's Finalize method, it will be removed from the latter list and unless a reference has been stored somewhere else, it will cease to exist.

The reason Image has a dispose method is that its construction often asks for the creation of things that are not .NET objects and/or asks outside entities to do things on its behalf (eg grant exclusive read access to a file). If a Bitmap were abandoned without Dispose being called upon it, and if it didn't have a Finalize method, the Bitmap object would cease to exist, but any outside objects whose creation it requested would continue to exist, and any outside entities that were acting on its behalf would continue to do so.

Because the creation of a byte array does not require the construction of anything that isn't a .NET object, nor does it require any outside entitites to do anything on its behalf, there is no need for an array which is no longer required to do anything other than cease to exist. Likewise for an object which holds such an array.

Memory consumption reduces in two cases:

  1. Garbage collector has freed up the memory, and
  2. Unmanaged code was executed which has freed up the memory instantaneously.

Image data example is the second case. Images are held by OS and when you dispose an image, operating system is called to free the image buffer. This is operating system's job because operating system is the one to render images on the screen, which then depends on hardware and drivers. In addition to this, graphical operating system is extremely optimized to work with image data - no wonder then that it is used to work with images when needed.

It is completely opposite when you create your own disposable class. Executing dispose actually does nothing, regarding the memory footprint. Even garbage collecting won't reduce the memory usage as long as there is a live pointer pointing to the disposed class.

Class should implement IDisposable only if it allocates some unmanaged resources - file handles, images, sockets (which are only a kind of file handles from OS point of view), etc. Dispose method is supposed to free up only the unmanaged resources. There is no point in setting the fields to null and do similar silly things.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM