After knowing how the type implements the Dispose pattern, take a look at how the developer uses the type that provides the dispose pattern. The previous SafeHandle class is no longer discussed here, but rather the more commonly used FileStream class is discussed.
You can use FileStream to open a file, read bytes from a file, write bytes to a file, and close the file. When a FileStream object is constructed, it calls the Win32 CreateFile function, the handle returned by the function is saved in Safefilehandle, and the reference to the object is maintained by a private field of the FileStream object. FileStream also provides additional properties (such as length,position,canread, etc.) and methods (for example: Read,write,flush, etc.).
Suppose you want to write code to create a temporary file, write some bytes into it, and then delete the file. You might start writing code like this:
Unfortunately, the above code is generated and run, it may work, but in most cases it is not, the problem is that the Delete method of file requires the window to delete a file that is still open. So the Delete method throws a IOException exception.
But in some cases, files may be "accidentally" deleted! If another thread does not know how to cause a garbage collection, and this garbage collection happens just after the call to write, and before the call to delete, then the Finalize method of the FileStream safefilehandle field is called, which closes the file. The delete operation will then work as well. The probability of this happening is very small, the above code can not be run more than 99% probability.
Fortunately, FileStream implements the Dispose mode, so you can modify the code to display the amount of closed files. Here is the source code after the modification:
static void Main (string[] args)
{
byte[] Bytewrite = new byte[] {1, 2, 3, 4, 5};
FileStream fs = new FileStream ("Temp.dat", FileMode.Create);
Fs. Write (bytewrite, 0, bytewrite.length);
Fs. Dispose ();
File.delete (@ "d:\ user directory \ My Documents \visual Studio 2010\projects\consoleapplication1\consoleapplication1\bin\debug\ Temp.dat ");
}
The only difference between the above code is the addition of the call to the FileStream Dispose method. The call to the Dispose method takes a Dispose method of the Boolen parameter, which calls the Dispose method on the SafeHandle object, which calls the CloseHandle function of Win 32, causing Windows to close the file, Then when the file's Delete method is called, Window discovers that it is closed, so it is successfully deleted. Since FileStream also provides a close method, it can also be closed with the Close method.
Note: The Close method is not a formal part of the Dispose class, some provide a close method, and some do not.
It is important to note that the call to dispose or close is only for the purpose of forcing the object to perform cleanup on a certain event, and these two methods do not control the lifetime of memory consumed by objects in the managed heap. This means that even if an object has been cleaned up, throwing can invoke the method above it. The following code shows the call to the Write method after shutting down, attempting to write more bytes to the file, showing that the byte cannot be written to the file. When the code executes, the second call to the Write method throws a System.objectdisposedexception exception and displays the following word a: The closed file cannot be accessed.
There is no memory corruption here, because the memory of the FileStream object is still "alive". Only after the cleanup has been performed, the object can no longer successfully execute its method.
Important: I do not support the call to dispose and close methods without brains. The reason is that the CLR's garbage collection period has been very well done and should be given the job to do. The garbage collection period knows when an object is no longer invoking the code of the application, and it is only then recycled, and when the application calls the Dispose or Close method, it actually swears that it knows when the application does not need an object, but for the application, It is impossible to know when an object is not needed.
For example, suppose you construct a new object in the code of method A and then pass a reference to the object to method B, and Method B may save a reference to the object in an internal field variable (a root). However, method A does not know this, and of course it can call the Dispose and close methods, but after that, other code may try to access the object, causing a objectdisposedexception to run out.
It is recommended that you call Dispose or close only in the following two cases: determine that you must clean up the resource, or that you can safely call Dispose or close, and that you want to remove the object from the finalization list, preventing the object from being offered to another generation, thereby improving performance.
Section seventh: Using types that implement the Dispose pattern